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

# Travel Rule FATF API: conformità VASP

> Didit: messaggistica Travel Rule FATF per VASP e PSP crypto, scambio dati di ordinante e beneficiario, monitoraggio protocolli. $0.02 per scambio.

Didit gestisce lo scambio tra ordinante e beneficiario previsto dalla normativa FATF e dal Regolamento UE sul trasferimento di fondi (TFR) per i trasferimenti di asset virtuali: individua un canale che raggiunge il VASP della controparte, negozia su di esso i dati richiesti, monitora lo scambio attraverso un ciclo di vita a 13 stati e ti comunica quando lo scambio si è concluso, così da poter rilasciare i fondi on-chain.

## Overview

Il Travel Rule del GAFI (Raccomandazione 16), recepito nell'UE come Regolamento sul trasferimento dei fondi (Transfer of Funds Regulation, TFR), impone al prestatore di servizi per le attività virtuali mittente (il **VASP ordinante**) di raccogliere e trasmettere i dati dell'ordinante e del beneficiario al prestatore di servizi per le attività virtuali ricevente (il **VASP beneficiario**) prima che il trasferimento di attività virtuali venga regolato.

A differenza della maggior parte delle giurisdizioni, il TFR dell'UE si applica **senza alcun importo minimo**: ogni trasferimento di cripto-attività rientra nell'ambito, non solo quelli sopra una soglia di segnalazione.

Il prodotto Travel Rule di Didit è uno scambio gestito, non solo un campo dati:

* Invii un trasferimento con `transaction_category: "travelRule"`.
* Didit prova i canali in ordine di priorità per raggiungere il VASP controparte, esegue lo scambio sul primo che lo raggiunge e, quando l'altra parte restituisce un nome del beneficiario, lo confronta con quello che hai inviato.
* Solo quando lo scambio raggiunge `COMPLETED` dovresti trasmettere il trasferimento on-chain.
* Comunichi quindi a Didit l'hash della transazione on-chain per chiudere lo scambio con stato `FINISHED`.

In questa release sono disponibili sette canali, provati in rigoroso ordine di priorità: vince il primo che può raggiungere la controparte.

| Priorità | Canale | Come funziona |
| - | - | - |
| 1 | `INTERNAL` | Usato quando un altro cliente di Didit ha dimostrato il controllo del wallet beneficiario con un messaggio firmato o un deposito di prova. Didit crea un trasferimento in entrata corrispondente sull'applicazione di quel cliente e negozia lo scambio interamente all'interno della piattaforma, senza alcuna chiamata di rete in uscita. Immediato. |
| 2 | `TRP` | Integrazione nativa con il protocollo aperto Travel Rule Protocol (TRP / OpenVASP). Usato quando il trasferimento include una [Travel Address](#travel-address), la voce della rubrica del wallet di destinazione ne contiene una, oppure il VASP controparte si risolve nella [directory](#directory) con un endpoint TRP. Supporta gli asset elencati in [identificatori degli asset TRP](#identificatori-di-asset-trp). Didit scambia i dati dell'ordinante e del beneficiario da macchina a macchina, senza passaggi via email. |
| 3 | `GTR` | Rete Global Travel Rule (GTR). La controparte viene risolta tramite un `counterparty_gtr_vasp_code` esplicito o una voce della directory che lo contiene. Didit legge la risposta della controparte dalla risposta di GTR, oppure interrogando lo stato della richiesta ogni 5 minuti mentre il trasferimento è in attesa. |
| 4 | `TRUST` | Rete TRUST. La controparte viene risolta tramite `counterparty_trust_membership_id` o una voce della directory che lo contiene. Solo invio: TRUST non restituisce nulla che Didit possa leggere, quindi il trasferimento resta in `AWAITING_COUNTERPARTY` fino alla scadenza. |
| 5 | `VERIFYVASP` | Rete VerifyVASP. La controparte viene risolta tramite `counterparty_verifyvasp_id` o una voce della directory che lo contiene. Didit legge la risposta della controparte interrogando lo stato della verifica ogni 5 minuti. |
| 6 | `SYGNA` | Rete Sygna Bridge (acquisita da VerifyVASP nel 2026, ancora operativa per i membri esistenti). Implementazione nativa del protocollo Sygna: IVMS101 cifrato con ECIES e richieste di autorizzazione firmate. La controparte viene risolta tramite `counterparty_sygna_vasp_code` o una voce della directory che lo contiene. La risposta di accettazione o rifiuto della controparte completa o rifiuta il trasferimento: Didit interroga lo stato del trasferimento ogni 5 minuti e riceve la risposta anche tramite il suo callback Sygna, non appena l'host pubblico TRP di Didit sarà attivo. |
| 7 | `EMAIL` | Ripiego usato quando nessun canale di protocollo o di rete raggiunge la controparte e indichi il suo contatto di compliance in `counterparty_vasp_email`, oppure la voce della directory della controparte ha un [contatto di compliance](#contatti). Didit invia a quel contatto un link di ritiro monouso con cui può confermare o rifiutare lo scambio senza un account Didit. È il canale principale per il problema del sunrise: le controparti non ancora raggiungibili su nessuna rete. |

Le reti (`GTR`, `TRUST`, `VERIFYVASP`, `SYGNA`) richiedono un'adesione alla rete dal lato mittente, e oggi tale adesione deve essere la tua.
Collega le credenziali di adesione nel **Marketplace** della console (categoria Reti Travel Rule), e i tuoi trasferimenti vengono effettuati con la tua identità di rete.

**Didit non ha alcuna adesione alla piattaforma per nessuna delle quattro reti oggi, e sta effettuando l'onboarding come fornitore per queste reti.**
Fino al completamento di tale onboarding, `platform_available` è `false` per tutte e quattro, la modalità `didit` nelle impostazioni (instradamento tramite l'adesione alla piattaforma di Didit) non è disponibile per nessuna rete, e `disabled_networks` non ha nulla da disattivare.
Un'adesione che colleghi tu stesso ha sempre la precedenza su un'adesione della piattaforma.
Nessuna adesione a una rete è inclusa di default, GTR compreso.
Abilitare Travel Rule non attiva GTR, TRUST, VerifyVASP o Sygna.
Consulta [Ottieni le impostazioni Travel Rule](https://docs.didit.me/it/management-api/travel-rule/get-settings.md) per le modalità `networks` effettive della tua applicazione, e [reti Travel Rule](https://docs.didit.me/it/transaction-monitoring/travel-rule-networks.md) per ciò che ciascuna rete raggiunge oggi.
Se tutte e quattro risultano `unavailable`, nessuna può instradare uno scambio: collega una tua adesione in **Marketplace**, oppure usa una controparte raggiungibile tramite `INTERNAL`, `TRP` o `EMAIL`.

Quando salvi un'adesione, il suo codice partecipante deve essere tuo: il salvataggio restituisce `400` se il codice è quello di Didit su quella rete, oppure un codice già detenuto dall'adesione di un'altra applicazione.
Un'adesione GTR richiede la propria chiave privata ed25519 (base64), quella la cui chiave pubblica è registrata nel portale GTR: cifra i dati personali che invii e decifra quelli che ricevi.
Un'adesione VerifyVASP punta al tuo Enclave VerifyVASP: il suo URL è quello del tuo Enclave e il suo token è quello che il tuo Enclave presenta a Didit.

Anche con una tua adesione, un canale di rete instrada un trasferimento solo se il suo `beneficiary_data` contiene l'id della controparte su quella rete (`counterparty_gtr_vasp_code`, `counterparty_trust_membership_id`, `counterparty_verifyvasp_id` o `counterparty_sygna_vasp_code`), oppure se la voce della directory della controparte lo elenca per quella rete (vedi [Instradamenti](#route)).

`platform_available` indica se l'adesione alla piattaforma è configurata, non un controllo dello stato della rete in tempo reale. Analogamente, `connected` significa che le tue credenziali di adesione sono salvate e hanno superato la validazione locale; il primo scambio reale le verifica con la rete. Una modalità `didit` o `own` non garantisce che la controparte sia raggiungibile né che la consegna vada a buon fine.

Con la tua iscrizione, Didit legge la risposta della controparte su `GTR`, `VERIFYVASP` e `SYGNA` dalla risposta della rete oppure interrogando la rete ogni 5 minuti, e completa o rifiuta il trasferimento.
`TRUST` prevede solo l'invio: un trasferimento inviato tramite questo canale resta in `AWAITING_COUNTERPARTY` finché non sono trascorse le ore indicate da `confirmation_timeout_hours`, poi passa a `EXPIRED` e si applica il tuo `timeout_outcome`.
La ricezione di un trasferimento che un altro VASP ti invia tramite una rete non è ancora attiva, e nessuno scambio su una rete è stato ancora completato con una rete in produzione: vedi [Reti Travel Rule](https://docs.didit.me/it/transaction-monitoring/travel-rule-networks.md).

Altre reti (CODE, l'alleanza coreana, TRISA, Notabene e Veriscope) sono elencate nel **Marketplace** della console come riquadri di richiesta di accesso.
Didit non ha ancora alcuna integrazione con queste reti, quindi oggi nessun trasferimento può essere instradato su di esse.

Quando nessuno dei sette canali riesce a identificare una controparte, Didit esegue un ulteriore passaggio di risoluzione prima di rinunciare: l'attribuzione tramite analisi blockchain.
Il wallet di destinazione viene cercato nei dati di analisi blockchain; quando il wallet appartiene a un exchange o a un custode noto, Didit registra il VASP attribuito sul trasferimento, lo aggiunge alla [directory](#directory) ed esegue di nuovo i canali una sola volta con il nuovo nome.
Vedi [Attribuzione tramite analisi blockchain](#attribuzione-tramite-analisi-blockchain) per il comportamento completo e i prezzi.

Un trasferimento la cui destinazione è [dichiarata come wallet in autocustodia](#wallet-in-autocustodia-dichiarati) salta tutti e sette i canali, poiché non esiste un VASP controparte con cui scambiare dati, e passa direttamente alla prova di proprietà del wallet da parte dell'utente finale.

> [!NOTE]
>
> Didit gestisce anche il lato rivolto alla controparte dello scambio: endpoint pubblici TRP per l'identità e le richieste di informazioni che gli altri VASP chiamano per raggiungerti, endpoint di callback e il flusso di recupero via email.
> Non li chiami mai tu stesso: sono infrastruttura gestita, ma la pagina [Interoperabilità Travel Rule](https://docs.didit.me/it/transaction-monitoring/travel-rule-interoperability.md) documenta ciascuno di essi affinché i VASP controparte possano connettersi a te.
> Interagisci con Travel Rule solo tramite gli endpoint `/v3/` descritti in questa pagina.

## Cosa viene eseguito quando invii un trasferimento

I controlli vengono eseguiti all'interno dell'unica chiamata `POST /v3/transactions/` - quando ricevi la risposta, lo screening è stato completato, il trasferimento è stato salvato e le regole sono state valutate.
Lo scambio vero e proprio inizia dopo la risposta: Didit sceglie il rail e contatta la controparte al di fuori della tua richiesta, quindi nessuna rete o controparte può rallentare o far fallire la creazione.
Ogni cambio di stato successivo arriva come webhook [`travel_rule.status.updated`](#webhook) che indica il rail, e l'oggetto del trasferimento restituito dagli endpoint dei trasferimenti Travel Rule contiene un campo [`delivery`](#consegna-e-nuovi-tentativi) che mostra se il messaggio è stato recapitato.
Non esiste alcuna pipeline da interrogare; le parti asincrone sono lo scambio, la risposta della controparte e qualsiasi azione dell'utente finale.

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

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

Passo dopo passo:

1. **Validazione e associazione del soggetto.** Il payload viene validato.
   Un `transaction_id` già usato nella tua applicazione viene rifiutato con `400`, e quando due richieste con lo stesso id arrivano in concorrenza, una delle due riceve `409`.
   Il `subject` viene collegato al tuo profilo utente o aziendale tramite `vendor_data`, così il trasferimento compare su quel profilo per il monitoraggio.
   Un `vendor_data` del soggetto o della controparte presente in blocklist viene rifiutato con `400`, e nessuna transazione viene creata.
   I wallet, i conti bancari, gli IP e i dispositivi in blocklist vengono controllati al passo 6 e fanno sì che la transazione venga rifiutata al passo 6, dopo che il routing è stato eseguito.
2. **Arricchimento di dispositivo e rete.** Gli IP delle parti vengono arricchiti con le informazioni geografiche, e qualsiasi contesto del dispositivo (automatico in caso di [invio tramite SDK](https://docs.didit.me/it/transaction-monitoring/sdk-transaction-submission.md)) viene normalizzato nel grafo dei dispositivi - lo stesso grafo alimentato dalle sessioni KYC, così la relazione "collegati per dispositivo" funziona tra onboarding e transazioni.
3. **Screening crypto.** Per i trasferimenti crypto con il monitoraggio attivo, il wallet pertinente (o l'hash on-chain) viene sottoposto allo screening rispetto alle analisi blockchain prima che si avvii qualsiasi scambio - esposizione a sanzioni, vicinanza a mixer, fondi rubati. Vedi [Screening crypto e dei wallet](https://docs.didit.me/it/transaction-monitoring/aml-screening.md).
4. **Trasferimento Travel Rule.** Il motore di scambio verifica la soglia e tiene conto di una [dichiarazione di wallet in autocustodia](#wallet-in-autocustodia-dichiarati), poi salva il trasferimento: `NOT_APPLICABLE` sotto la tua soglia, `UNCONFIRMED_OWNERSHIP` per un wallet in autocustodia dichiarato, `COMPLETED` quando l'altro wallet è un tuo wallet verificato, e `AWAITING_COUNTERPARTY` negli altri casi, con il rail ancora vuoto.
   Ogni cambio di stato accoda un evento `travel_rule.status.updated`, e Didit lo invia dopo `transaction.created` della transazione (passo 7).
5. **Generazione della verifica della proprietà del wallet.** Se il trasferimento richiede la prova di controllo da parte dell'utente finale e `auto_wallet_verification` è attivo, viene generata una sessione del [widget di verifica della proprietà del wallet](https://docs.didit.me/it/transaction-monitoring/wallet-ownership-widget.md) e restituita in `action_required`.
6. **Valutazione delle regole.** Ogni regola attiva viene eseguita - il [bundle EU TFR](#bundle-di-regole-tfr-ue) reagisce allo stato del trasferimento impostato al passo 4, le tue regole personalizzate vedono l'output dello screening del passo 3, e una regola può trattenere la transazione (`IN_REVIEW`), rifiutarla o richiedere una [verifica rafforzata](https://docs.didit.me/it/transaction-monitoring/sdk-transaction-submission.md#azioni-richieste-all’utente) (`AWAITING_USER`).
7. **Fatturazione e notifica.** Una transazione in uscita viene fatturata su un'unica voce: la [voce Travel Rule](#prezzi) quando ha avviato uno scambio, e Transaction Screening negli altri casi. Un trasferimento in entrata non comporta alcuna commissione, e un'applicazione sandbox non viene mai addebitata.
   La risposta viene restituita, `transaction.created` viene inviato alle tue destinazioni webhook, seguito dagli eventi `travel_rule.status.updated` del passo 4.
8. **Routing, dopo la risposta.** Didit percorre i [sette rail](#overview) in ordine di priorità; se nessuno dà esito, l'[attribuzione tramite analisi blockchain](#attribuzione-tramite-analisi-blockchain) identifica la controparte e i rail vengono rieseguiti una sola volta. Il primo rail raggiungibile gestisce lo scambio: il trasferimento resta `AWAITING_COUNTERPARTY` su quel rail mentre la controparte risponde, viene regolato subito quando viene trovata una controparte `INTERNAL` (`COMPLETED` oppure `COUNTERPARTY_MISMATCHED_DATA`), oppure diventa `COUNTERPARTY_VASP_NOT_FOUND` quando nessun rail raggiunge la controparte. Ogni cambiamento invia `travel_rule.status.updated`, e le tue regole vengono rieseguite ogni volta che cambiano lo stato o il rail. Un trasferimento che il routing lascia in `COUNTERPARTY_VASP_NOT_FOUND` riceve in quel momento la sessione del widget di verifica della proprietà del wallet (quando `auto_wallet_verification` è attivo); la leggi da `action_required` della transazione con [Get transaction](https://docs.didit.me/it/management-api/transactions/get.md).

### Come ogni passo corrisponde ai tuoi obblighi

| Passo della pipeline | Obbligo che assolve |
| - | - |
| Dati dell'ordinante che fornisci in `originator_data` | Informazioni accurate sull'ordinante (FATF R.16; EU TFR Art. 14). Sui rail che trasportano dati delle persone (`INTERNAL`, `TRP` e i rail di rete), Didit trasmette l'identità verificata quando il soggetto è un utente con una verifica KYC Didit approvata (vedi [Dati verificati e provenienza](#dati-verificati-e-provenienza)), altrimenti esattamente i dati `originator_data` che invii. |
| Scambio sui rail prima del regolamento | Informazioni sull'ordinante e sul beneficiario trasmesse alla VASP controparte **prima** che il trasferimento venga regolato (FATF R.16; EU TFR Art. 14-16) |
| Confronto del nome del beneficiario | Verifica che i dati del beneficiario corrispondano alla destinazione (obblighi EU TFR Art. 16 del CASP del beneficiario) |
| Prova della proprietà del wallet in autocustodia | L'obbligo EU TFR sui wallet in autocustodia - verificare la proprietà di un indirizzo non custodito invece di scambiare con una VASP |
| Screening crypto + bundle di regole EU TFR | Procedure basate sul rischio per trasferimenti con informazioni mancanti o incomplete, e controlli sull'esposizione a sanzioni |
| Condizione `COMPLETED` prima della trasmissione | I fondi non vengono sbloccati finché lo scambio non si conclude - il cuore della regola |
| Chiusura `FINISHED` con l'hash on-chain + timeline | Conservazione delle registrazioni: ogni trasferimento conserva la sua cronologia completa della negoziazione ai fini di audit |

> [!NOTE]
>
> **Nota sui test.** Le applicazioni sandbox ignorano la valutazione delle regole e la fatturazione, e non inviano alcun webhook `transaction.created` o `transaction.status.updated`. Le transazioni sandbox restano `APPROVED` a meno che un trasferimento Travel Rule con scadenza applichi il tuo `timeout_outcome`, e non viene addebitato nulla.
> Il motore di scambio Travel Rule vero e proprio viene eseguito sulle applicazioni sandbox quando Travel Rule è abilitato, con una sola controparte: ogni scambio **in uscita** va alla [Didit Test VASP](https://docs.didit.me/it/transaction-monitoring/travel-rule-sandbox.md) sul rail `TEST_VASP`, che risponde all'interno di Didit con lo scenario che scegli, così il trasferimento viene completato, rifiutato, risulta in mancata corrispondenza, diventa irraggiungibile, scade o attende la verifica della proprietà del wallet.
> Nessun messaggio di compliance raggiunge mai una VASP controparte reale, e i webhook `travel_rule.status.updated` vengono consegnati con `environment: sandbox`.
> **In entrata**, il VASP di test può inviarti un trasferimento ([Trigger Test VASP Inbound Transfer](https://docs.didit.me/it/management-api/travel-rule/trigger-test-vasp-inbound.md)), e la registrazione (`POST /v3/travel-rule/inbound/`) si regola sulla tua rubrica dei wallet come su un'applicazione di produzione - `ON_HOLD`, `UNCONFIRMED_OWNERSHIP`, `COUNTERPARTY_MISMATCHED_DATA`, oppure `COMPLETED` seguito da `FINISHED`.
> Vedi [Testare Travel Rule in sandbox](https://docs.didit.me/it/transaction-monitoring/travel-rule-sandbox.md).

## Ciclo di vita

Ogni trasferimento ha uno `status` scelto tra 13 valori.
Lo scambio inizia con `AWAITING_COUNTERPARTY` nel caso normale, con `NOT_APPLICABLE` quando l'importo è inferiore al tuo `threshold_amount` oppure una richiesta di pagamento Lightning non indica un beneficiario (vedi [Lightning](#lightning)), oppure con `UNCONFIRMED_OWNERSHIP` quando la destinazione è stata [dichiarata un wallet in autocustodia](#wallet-in-autocustodia-dichiarati). Termina in uno degli stati finali: `FINISHED`, `CANCELLED` o `EXPIRED`.

Il trasferimento segue una propria macchina a stati, **separata** dallo stato di revisione della transazione sottostante.
Lo stato dello scambio non modifica mai da solo lo stato della transazione, con un'unica eccezione: alla scadenza si applica il tuo `timeout_outcome` configurato (oppure una [politica sunrise o per mancata risposta](#politiche-sunrise-e-per-le-controparti-non-responsive), quando ne è applicabile una).
Le tue regole vengono rieseguite a ogni transizione, quindi le [regole EU TFR](#bundle-di-regole-tfr-ue) o qualsiasi regola basata su `travel_rule_status` possono spostare la transazione, ad esempio in `IN_REVIEW`.
Un trasferimento che richiede la prova del controllo del wallet da parte dell'utente finale aggiunge un blocco `action_required` alla transazione, ma il suo `status` resta quello definito dalle tue regole.
Leggi lo stato dello scambio da `travel_rule.status`; leggi il verdetto di autorizzazione / sospensione / rifiuto dallo `status` della transazione stessa.

Ogni transizione (e ogni stato riportato passivamente) viene anche replicato nei valori personalizzati della transazione, così le [regole](https://docs.didit.me/it/transaction-monitoring/rules.md) possono basarsi su di essi: `custom_values.travel_rule_status` (stato canonico), `custom_values.travel_rule_rail` (il canale che ha trasportato lo scambio, vuoto finché non ne viene selezionato uno) e `custom_values.travel_rule_regime` (derivato dal `jurisdiction` nelle tue [impostazioni](#configurazione): `SG` → `singapore`, `GB` → `uk` e qualsiasi codice di membro UE o SEE, come `DE` o `FR`, → `eu`; i codici non mappati vengono scritti in minuscolo, ad esempio `US` → `us`. Un `props.travel_rule_regime` che invii tu ha sempre la precedenza sul valore derivato).

| Stato | Significato |
| - | - |
| `AWAITING_COUNTERPARTY` | Il trasferimento attende la controparte: prima mentre Didit sceglie il canale e invia lo scambio, subito dopo la creazione, poi mentre la controparte risponde. La [`delivery`](#consegna-e-nuovi-tentativi) del trasferimento indica se il messaggio è arrivato. `TRUST` si limita a inviare, quindi un trasferimento su di esso resta in questo stato fino alla scadenza. |
| `UNCONFIRMED_OWNERSHIP` | Il trasferimento attende la prova del controllo del wallet. Si raggiunge quando il wallet della controparte è stato [dichiarato in autocustodia](#wallet-in-autocustodia-dichiarati) all'invio (in uscita o in entrata), oppure quando un trasferimento in entrata corrisponde a una [voce della rubrica](#rubrica-degli-indirizzi-wallet) la cui titolarità non è ancora verificata. Avanza tramite il [widget di verifica della titolarità del wallet](https://docs.didit.me/it/transaction-monitoring/wallet-ownership-widget.md) o [`POST .../travel-rule/ownership/`](#conferma-dell’assetto-proprietario-del-wallet). |
| `ON_HOLD` | Didit lo imposta solo sui trasferimenti in entrata: il wallet di destinazione di una [registrazione dopo il deposito](#registrazione-postuma-del-deposito-sunrise) o di una richiesta `TRP` in entrata non è presente nella tua [rubrica](#rubrica-degli-indirizzi-wallet), oppure una richiesta `TRP` in entrata attende la tua decisione (l'accettazione automatica è disattivata o la risposta automatica non ha potuto essere consegnata). Risolvilo con [`POST .../travel-rule/ownership/`](#conferma-dell’assetto-proprietario-del-wallet). Non modifica da solo lo stato della transazione; la [regola di libreria](https://docs.didit.me/it/transaction-monitoring/rules-library.md) opt-in `travel-rule-pending-action` sposta tali transazioni in `AWAITING_USER`. |
| `COMPLETED` | Lo scambio si è concluso con successo: la controparte (oppure, su un trasferimento in entrata, tu) lo ha approvato, oppure sono stati superati i controlli che Didit esegue su quel percorso (corrispondenza del nome del beneficiario, prova di controllo del wallet). È sicuro trasmettere il trasferimento on-chain. |
| `FINISHED` | Lo scambio è chiuso con l'hash della transazione on-chain. Su un trasferimento in uscita, tu comunichi l'hash tramite [`PATCH .../travel-rule/`](#invio-di-un-trasferimento). Su un trasferimento in entrata, Didit lo imposta quando il deposito è già stato regolato ([registrazione dopo il deposito](#registrazione-postuma-del-deposito-sunrise)), quando l'ordinante conferma un trasferimento `TRP`, oppure quando il lato `INTERNAL` in uscita termina. |
| `CANCELLED` | Annullato manualmente con `action: "cancel"` da qualsiasi stato non finale, oppure annullato dall'ordinante di un trasferimento `TRP` in entrata. |
| `EXPIRED` | È trascorso `confirmation_timeout_hours` mentre era in `AWAITING_COUNTERPARTY`. Un processo di scansione (ogni 15 minuti) fa scadere il trasferimento e applica alla transazione sottostante il tuo `timeout_outcome` configurato: `REJECT` la rifiuta, `HOLD` la sposta in revisione, `PROCEED` la lascia invariata. La tua [politica sunrise o per mancata risposta](#politiche-sunrise-e-per-le-controparti-non-responsive) sostituisce `timeout_outcome` quando ne è applicabile una. |
| `COUNTERPARTY_MISMATCHED_DATA` | Il nome del beneficiario non ha soddisfatto il `name_matching_strictness` configurato rispetto all'altra parte: il nome restituito dalla controparte, oppure il `holder_name` della voce della rubrica corrispondente. |
| `COUNTERPARTY_VASP_NOT_FOUND` | Nessuno dei sette canali, né il fallback di [attribuzione tramite analisi blockchain](#attribuzione-tramite-analisi-blockchain), è riuscito a individuare un VASP controparte raggiungibile per questo trasferimento. Un'entità attribuita viene comunque registrata sul trasferimento e nella directory. Sui trasferimenti in uscita, Didit crea automaticamente una sessione del [widget di verifica della titolarità del wallet](https://docs.didit.me/it/transaction-monitoring/wallet-ownership-widget.md) (quando `auto_wallet_verification` è attivo), così il trasferimento può comunque completarsi come trasferimento verso un wallet in autocustodia. `reason` e `next_actions` spiegano il motivo e cosa lo fa avanzare: vedi [Perché un trasferimento è bloccato](#perché-un-trasferimento-è-bloccato). |
| `COUNTERPARTY_VASP_NOT_REACHABLE` | È stato identificato un VASP controparte, ma il canale selezionato non è riuscito a consegnare: la sua identità `TRP` o il suo endpoint per le richieste non è raggiungibile, l'identità dichiarata non corrisponde a `counterparty_vasp_lei` o `counterparty_vasp_name`, una rete ha rifiutato il messaggio o non lo ha accettato dopo sei tentativi (vedi [Consegna e nuovi tentativi](#consegna-e-nuovi-tentativi)), oppure il provider di posta ha rifiutato l'email di conformità. `reason` distingue questi casi e `next_actions` indica cosa fa avanzare il trasferimento: vedi [Perché un trasferimento è bloccato](#perché-un-trasferimento-è-bloccato). Riprova con `action: "resend"` quando sarà di nuovo raggiungibile. |
| `COUNTERPARTY_VASP_GENERAL_DECLINE` | La controparte ha rifiutato lo scambio: titolarità negata, la controparte ha rifiutato di prendere in carico l'email, oppure un rifiuto `TRP` o Sygna. |
| `NOT_ENOUGH_COUNTERPARTY_DATA` | Una richiesta `TRP` in entrata non ha identificato il beneficiario né tramite il nome né tramite l'indirizzo, quindi Didit non ha potuto associarla alla tua rubrica. Né l'endpoint di titolarità né `resend` accettano un trasferimento in entrata di questo tipo: puoi solo annullarlo, e annullarlo non risponde alla richiesta della controparte. Didit non lo imposta mai su un trasferimento in uscita; se lo registri tu su uno di questi, `action: "resend"` riesegue l'instradamento. |
| `NOT_APPLICABLE` | L'importo del trasferimento era inferiore alla `threshold_amount` configurata, una richiesta di pagamento [Lightning](#lightning) in uscita non indica alcun beneficiario (`chain_details.not_applicable_reason` spiega il motivo), oppure hai registrato tu questo stato con la Travel Rule disattivata (inclusi i valori legacy `UNKNOWN` e `EXEMPT`, vedi sotto). |

> [!WARNING]
>
> **Non trasmettere mai prima di `COMPLETED`.**
> Rilasciare i fondi on-chain mentre un trasferimento è in `AWAITING_COUNTERPARTY`, `UNCONFIRMED_OWNERSHIP` o in qualsiasi stato di mancata corrispondenza o rifiuto vanifica lo scopo dello scambio.
> Subordina il passaggio di trasmissione a `status == "COMPLETED"`, poi chiama `PATCH .../travel-rule/` con il `payment_txn_id` risultante per passare a `FINISHED`.

Le transizioni in sintesi (`CANCELLED` è inoltre raggiungibile da ogni stato non finale con `action: "cancel"`):

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

### Consegna e nuovi tentativi

Didit invia ogni messaggio dovuto da un trasferimento al di fuori della richiesta che lo ha generato, e lo ritenta finché l'altra parte non lo accetta.
L'oggetto trasferimento restituito da [Completamento, annullamento o reinvio](https://docs.didit.me/it/management-api/travel-rule/update-transfer.md), [Conferma dell'assetto proprietario](https://docs.didit.me/it/management-api/travel-rule/confirm-ownership.md) e [registrazione sunrise](#registrazione-postuma-del-deposito-sunrise) contiene l'ultimo messaggio in `delivery`, e lo stesso vale per l'oggetto `travel_rule` incorporato nella transazione; è `null` quando il trasferimento non ne ha mai dovuto inviare uno.

| Campo | Significato |
| - | - |
| `kind` | `SEND` (il primo messaggio alla controparte), `ANSWER` (la tua accettazione o il tuo rifiuto, dovuto alla rete che l'ha richiesto), `TXID` (l'hash on-chain, dopo che hai completato il trasferimento), `CANCEL` (dopo che lo hai annullato), oppure `POLL` (una query di stato a una rete che la offre, ogni 5 minuti mentre il trasferimento attende la controparte). |
| `status` | `QUEUED`, `SENDING`, `RETRYING`, `DELIVERED` o `FAILED`. |
| `rail` | Il canale che trasporta il messaggio; vuoto finché Didit non ne ha scelto uno per un primo messaggio. |
| `attempts` | Tentativi effettuati finora. |
| `last_error` | Il motivo del fallimento dell'ultimo tentativo, vuoto se nessun tentativo è fallito. Un breve motivo che indica il passaggio e il tipo di errore, per esempio `sygna permission request failed: HTTP 503` o `sygna status query failed: no answer in time`; quando GTR risponde con un errore, sono inclusi il suo codice di stato e il suo messaggio. I corpi delle risposte non sono mai inclusi. |
| `next_attempt_at` | Quando viene eseguito il tentativo successivo, mentre il messaggio è in stato `QUEUED` o `RETRYING`. |
| `delivered_at` | Quando l'altra parte ha accettato il messaggio. |

Per un errore da cui la rete potrebbe ancora riprendersi (nessuna risposta in tempo, connessione non riuscita, HTTP `408`, `429` o `5xx`) viene effettuato un nuovo tentativo dopo 30 secondi, 2 minuti, 10 minuti, 30 minuti e 1 ora.
Quando un primo messaggio fallisce in modo definitivo (la rete lo ha rifiutato, oppure è fallito anche il sesto tentativo), il trasferimento passa a `COUNTERPARTY_VASP_NOT_REACHABLE` con `last_error` nella sua `timeline`, e puoi riprovare con `action: "resend"`.
Qualsiasi altro messaggio che fallisce in modo definitivo viene annotato nella `timeline`.
`delivery` non sostituisce mai lo `status` del trasferimento: leggi lo scambio dallo `status` e usa `delivery` per capire perché un trasferimento è ancora in attesa.

### Valori di stato legacy

Se inviavi già `travel_rule_details.status` prima di questa versione, quei valori continuano a funzionare e vengono mappati automaticamente.
I nomi in camelCase di qualsiasi stato (per esempio `counterpartyVaspNotFound`) sono accettati anche in fase di invio e nei valori delle condizioni delle [regole](https://docs.didit.me/it/transaction-monitoring/rules.md), e vengono normalizzati nella forma canonica:

| Valore legacy | Mappato a |
| - | - |
| `UNKNOWN` | `NOT_APPLICABLE` |
| `COMPLIANT` | `COMPLETED` |
| `PENDING_ACTION` | `ON_HOLD` |
| `PENDING_COUNTERPARTY` | `AWAITING_COUNTERPARTY` |
| `FAILED` | `CANCELLED` |
| `EXEMPT` | `NOT_APPLICABLE` |

## Configurazione

Configura il profilo VASP e la policy di negoziazione una sola volta per applicazione con `GET`/`PUT /v3/travel-rule/settings/`.

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

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

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

`PUT` è un aggiornamento parziale: invia solo i campi che vuoi modificare.

| Campo | Tipo | Descrizione |
| - | - | - |
| `is_enabled` | boolean | Attiva il flusso di negoziazione gestito per le transazioni `travelRule` in uscita da questa applicazione. Richiede un `legal_name` non vuoto (già salvato, oppure incluso nella stessa richiesta); in caso contrario la richiesta restituisce `400`. |
| `legal_name` | string | La ragione sociale del tuo VASP. Viene mostrata alla controparte nella pagina di ritiro via email e restituita nella [directory dei VASP](#directory). |
| `lei` | string | Il tuo Legal Entity Identifier, restituito nella directory dei VASP. |
| `jurisdiction` | string | Il codice della giurisdizione operativa del tuo VASP, fino a 8 caratteri (predefinito `"EU"`). |
| `name_matching_strictness` | string | `NONE`, `STRICT`, `CONTAINS`, `DEFAULT` oppure `FUZZY`; vedi sotto. |
| `confirmation_timeout_hours` | integer | Ore per cui un trasferimento `AWAITING_COUNTERPARTY` può restare in attesa prima della scadenza automatica. Minimo `1`, predefinito `48`. |
| `timeout_outcome` | string | Cosa succede alla transazione sottostante quando un trasferimento scade: `HOLD` la sposta in revisione, `REJECT` la rifiuta, `PROCEED` lascia invariato il suo stato. Predefinito `HOLD`. `sunrise_policy` e `non_responsive_policy` hanno la precedenza quando una delle due si applica. |
| `sunrise_policy` | string | `HOLD`, `REJECT`, `PROCEED` oppure `""` (predefinito) per seguire `timeout_outcome`: cosa fa un trasferimento scaduto quando la sua controparte è una voce della directory in una giurisdizione elencata in `sunrise_jurisdictions`. Vedi [Politiche relative al periodo di avvio e alla mancata risposta](#politiche-sunrise-e-per-le-controparti-non-responsive). |
| `non_responsive_policy` | string | `HOLD`, `REJECT`, `PROCEED` oppure `""` (predefinito) per seguire `timeout_outcome`: cosa fa un trasferimento scaduto quando la sua controparte è una voce della directory la cui [reattività](#reattività) è `UNRESPONSIVE`. `sunrise_policy` si applica per primo quando entrambe le condizioni valgono. |
| `sunrise_jurisdictions` | string\[] | Sola lettura. I paesi che Didit tratta come in un periodo di avvio della Travel Rule, attualmente `["CO", "KH", "VN"]`. Qualsiasi altra giurisdizione segue `timeout_outcome`. |
| `compliance_email` | string | Email del contatto di compliance per il profilo del tuo VASP. La [rete Didit](#la-rete-didit) elenca il tuo profilo solo dopo che questo indirizzo è stato confermato tramite un link inviato per email; modificarlo richiede una nuova conferma. |
| `is_discoverable` | boolean | Indica se il profilo del tuo VASP può essere inserito nella [rete Didit](#la-rete-didit): individuabile da altri clienti Didit in `GET /v3/travel-rule/vasps/` e raggiungibile tramite il canale INTERNAL. L'inserimento è soggetto ad altre condizioni; `didit_network` nelle impostazioni indica quali mancano. Predefinito `true`. |
| `inbound_auto_accept` | boolean | Se `true`, una richiesta `TRP` in ingresso il cui wallet beneficiario è una voce verificata nella tua rubrica degli indirizzi e il cui nome corrisponde viene approvata automaticamente. Se `false`, resta in `ON_HOLD` in attesa della tua decisione. Gli altri percorsi in ingresso non leggono questa impostazione. Predefinito `true`. |
| `allow_self_declaration` | boolean | Se `true`, il [widget di verifica della proprietà del wallet](https://docs.didit.me/it/transaction-monitoring/wallet-ownership-widget.md) offre l'autodichiarazione come metodo di prova, e puoi creare voci nella [rubrica degli indirizzi dei wallet](#rubrica-degli-indirizzi-wallet) con `self_declared: true`. Predefinito `true`. |
| `allow_screenshot_proof` | boolean | Se `true`, il [widget di verifica della proprietà del wallet](https://docs.didit.me/it/transaction-monitoring/wallet-ownership-widget.md) offre il caricamento di uno screenshot come prova della proprietà. Uno screenshot non verifica mai da solo il wallet: il tuo team di compliance lo esamina e conferma il trasferimento. È meno affidabile della firma crittografica; disattivalo dove la tua policy richiede una prova equivalente a una firma. Predefinito `true`. |
| `auto_wallet_verification` | boolean | Se `true`, un trasferimento in uscita che richiede la prova del controllo del wallet da parte dell'utente finale genera automaticamente una sessione del [widget di verifica della proprietà del wallet](https://docs.didit.me/it/transaction-monitoring/wallet-ownership-widget.md) collegata alla transazione e la mostra nel blocco `action_required` della transazione; gli SDK di Didit la avviano automaticamente all'[invio lato client](https://docs.didit.me/it/transaction-monitoring/sdk-transaction-submission.md). Predefinito `true`. |
| `counterparty_screening_enabled` | boolean | Screening facoltativo per sanzioni e notizie negative [sulle controparti VASP](#screening-della-controparte), fatturato per ogni screening al prezzo di Screening AML aziendale. Se `true`, Didit esegue lo screening della controparte raggiunta da uno scambio in uscita all'avvio dello scambio, riutilizzando uno screening di meno di 30 giorni. Predefinito `false`: non viene eseguito alcuno screening né addebitato alcun costo. |
| `vasp_attribution_enabled` | boolean | Se `true`, un trasferimento in uscita che nessun canale può instradare viene attribuito tramite [analisi blockchain](#attribuzione-tramite-analisi-blockchain): il wallet di destinazione viene ricondotto al VASP proprietario, l'entità viene aggiunta alla directory e i canali vengono rieseguiti una sola volta con il nome attribuito. Predefinito `true`. |
| `threshold_amount` | string (decimal) | Importo minimo del trasferimento che attiva uno scambio gestito, nella valuta predefinita della tua applicazione: Didit lo confronta con l'importo del trasferimento convertito in quella valuta (oppure con l'`amount_in_default_currency` che invii), non con l'importo nella valuta propria del trasferimento. I trasferimenti sotto questa soglia vengono risolti direttamente come `NOT_APPLICABLE` e non vengono mai negoziati. Se Didit non riesce a convertire l'importo, la soglia non viene applicata e il trasferimento viene scambiato. Le applicazioni sandbox non convertono gli importi, quindi lì la soglia si applica solo quando invii `amount_in_default_currency`. Il valore predefinito è `0.00`, in linea con la formulazione del TFR UE senza importo minimo, quindi ogni trasferimento viene verificato indipendentemente dall'importo. |
| `ownership_validation_mode` | string | `FULL`, `SIMPLIFIED` oppure `AUTOMATED`: quanta prova della proprietà di un wallet è richiesta. Vedi [Modalità di validazione della proprietà](#modalità-di-validazione-dell’assetto-proprietario). Predefinito `AUTOMATED`. |
| `simplified_validation_threshold` | string (decimal) | In modalità `SIMPLIFIED`, un trasferimento sotto questo importo accetta un'autodichiarazione. Predefinito `0.00`. |
| `data_sharing_fields` | object | I campi relativi ai tuoi utenti che invii, per tipo di entità. Vedi [Condivisione dei dati](#condivisione-dei-dati). |
| `matching_rules` | object | Quanto rigorosamente ogni campo dei dati della controparte viene confrontato, per tipo di entità. Vedi [Confronto per campo](#corrispondenza-per-campo). |
| `disabled_networks` | string\[] | Percorsi di rete (`GTR`, `TRUST`, `VERIFYVASP`, `SYGNA`) su cui i tuoi trasferimenti NON devono essere instradati tramite l'appartenenza alla piattaforma di Didit. Una rete a cui hai collegato una tua appartenenza (console Marketplace) non è mai interessata da questo elenco. Didit non dispone ancora di un'appartenenza alla piattaforma, quindi oggi l'elenco non ha alcun effetto sull'instradamento (un percorso elencato riporta `mode: off`). Predefinito `[]`. |
| `networks` | object | Sola lettura. Stato per rete, indicizzato con `gtr` / `trust` / `verifyvasp` / `sygna`: `{rail, mode, platform_available, connected}` dove `mode` è `own` (la tua appartenenza collegata), `didit` (appartenenza alla piattaforma di Didit, non ancora disponibile su nessuna rete), `off` (disattivata da te) oppure `unavailable`. |
| `travel_address` | string | Sola lettura. La Travel Address del tuo VASP, cioè l'endpoint di richiesta `TRP` in entrata codificato che gli altri VASP usano per raggiungerti. Viene compilata dopo l'attivazione della Travel Rule, ad esempio `ta2ih1MicegQ3JqiKz9xT89KsSuwaDJYw8DgzmeS5uNDp3dGW3bweBWLKws442chRsyNxmmJnyWc7frxjjSeABVsYR11UuBePkw6E`. |

### Rigore della corrispondenza dei nomi

| Valore | Comportamento |
| - | - |
| `NONE` | Viene accettato qualsiasi nome del beneficiario: non viene effettuato alcun confronto. |
| `STRICT` | Gli insiemi di token normalizzati dei due nomi devono essere esattamente uguali. |
| `CONTAINS` | Tutte le parole di un nome devono comparire nell'altro, per quanto poche siano. |
| `DEFAULT` | Ogni token del nome più breve deve comparire nel nome più lungo (corrispondenza di sottoinsieme), e il nome più breve deve avere almeno due token, a meno che i due nomi non siano identici. |
| `FUZZY` | Il rapporto di somiglianza delle stringhe normalizzate complete deve essere almeno `0.85`. |

### Modalità di validazione dell'assetto proprietario

`ownership_validation_mode` decide quanta prova serve per l'assetto proprietario di un wallet prima che un trasferimento possa basarsi su di esso:

| Modalità | Comportamento |
| - | - |
| `FULL` | È sempre richiesta una prova: un messaggio firmato, un deposito di prova o uno screenshot verificato. La parola dell'utente finale non vale mai. Il widget non offre `SELF_DECLARATION`, avviarne una restituisce `403`, e una voce della rubrica creata con `self_declared: true` restituisce `400`. |
| `SIMPLIFIED` | Un'autodichiarazione è accettata finché il trasferimento è sotto `simplified_validation_threshold`; sopra la soglia è richiesta una prova. Un trasferimento in entrata (una richiesta TRP, un messaggio di rete o un deposito che segnali) viene valutato in base al suo importo convertito nella valuta predefinita della tua applicazione al tasso corrente. Un asset senza tasso e ogni trasferimento di un'applicazione sandbox vengono considerati al di sopra della soglia. |
| `AUTOMATED` | La rubrica degli indirizzi e le prove precedenti dell'utente finale determinano autonomamente la validità, incluse le autodichiarazioni finché `allow_self_declaration` è `true`. È il valore predefinito ed è ciò che ogni applicazione faceva prima che esistessero le modalità. |

Un wallet viene ricordato per utente finale una volta verificato.
In `FULL` e `SIMPLIFIED`, un trasferimento successivo lo riutilizza solo se una prova accettata dalla modalità per quel trasferimento lo supporta.
Quando `inbound_auto_accept` non trova alcun wallet corrispondente nella rubrica, un wallet di criptovalute che hai registrato nelle transazioni di un solo utente finale identifica il titolare.
Didit aggiunge quel wallet alla rubrica dell'utente finale come tua autodichiarazione, verificato a meno che la modalità non sia `FULL`. Non aggiunge mai un wallet che la rubrica elenca già con un altro nome della stessa catena (`eth` ed `ethereum`), incluso quello registrato come appartenente a un altro VASP.
I controlli sugli indirizzi che gli altri VASP effettuano prima di inviare (tramite `GTR`, `Sygna` e `VerifyVASP`) seguono anch'essi la modalità: con `FULL`, un wallet che l'utente finale ha solo dichiarato non viene riportato come tuo.

### Condivisione dei dati

`data_sharing_fields` stabilisce quali campi Didit invia alla controparte sui tuoi utenti, separatamente per persone fisiche e aziende:

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

* Le persone fisiche possono condividere `name`, `wallet_address`, `address`, `national_id`, `customer_identification`, `date_of_birth` e `place_of_birth`. Le aziende usano i primi cinque.
* `name` e `wallet_address` vengono sempre inviati.
* Un tipo di entità che non hai mai scelto condivide tutti i campi. Un elenco vuoto è comunque una scelta: condivide solo il nome e il wallet.
* Un `PUT` unisce per tipo di entità, quindi inviare `individual` lascia invariata la scelta `company` salvata.
* Una scelta che non può soddisfare gli obblighi dell'ordinante previsti dal regime della tua `jurisdiction` (EU TFR o FATF Recommendation 16), compreso un elenco vuoto, viene rifiutata con `400`. Gli errori si trovano sotto `data_sharing_fields`, indicizzati per tipo di entità.

### Corrispondenza per campo

`matching_rules` stabilisce quanto rigorosamente ogni campo dei dati della controparte viene confrontato con quanto detieni:

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

Ogni valore è `NONE`, `STRICT`, `CONTAINS`, `DEFAULT` oppure `FUZZY`.
Valori predefiniti: `name` segue `name_matching_strictness`, `date_of_birth` e `address` sono `NONE`, e `account` è `STRICT`.
Un campo omesso mantiene il suo valore predefinito, e un campo che il tipo di entità non confronta (un'azienda non ha `date_of_birth`) viene rifiutato con `400`.

### Soglie per giurisdizione

`threshold_amount` esiste perché l'ambito della Travel Rule varia a seconda dell'autorità di vigilanza.
Didit usa come predefinito `0.00`, la posizione UE, quindi ogni trasferimento viene scambiato a meno che tu non alzi la soglia deliberatamente:

| Regime | Soglia | Note |
| - | - | - |
| **UE** - Regolamento sul trasferimento di fondi (UE) 2023/1113 | **Nessun minimo** | Ogni trasferimento crypto da CASP a CASP rientra nell'ambito. L'assetto proprietario di un wallet in autocustodia deve essere verificato per i trasferimenti superiori a EUR 1,000. |
| **Raccomandazione FATF 16** (base globale) | USD/EUR 1,000 | Sotto questa soglia, la FATF consente un insieme ridotto di dati (nomi e indirizzi dei wallet, senza verifica). |
| **Stati Uniti** - BSA Travel Rule | USD 3,000 | La soglia storica del FinCEN per i trasferimenti di fondi, applicata alle valute virtuali convertibili. |
| **Regno Unito** | EUR 1,000 equivalenti | Informazioni complete sopra la soglia; insieme ridotto di dati sotto di essa (MLRs Part 7A). |
| **Singapore** - MAS PSN02 | SGD 1,500 | Requisiti ridotti sotto la soglia. |
| **Svizzera** - FINMA | Nessun minimo | Informazioni richieste per tutti i trasferimenti; prova dell'assetto proprietario prevista per i wallet in autocustodia. |

Imposta `threshold_amount` sulla cifra fissata dalla tua autorità di vigilanza; i trasferimenti sotto di essa si risolvono in `NOT_APPLICABLE` senza scambiare alcun dato identificativo.
Le soglie cambiano: verifica la cifra attuale con il tuo consulente legale in ambito compliance, senza considerare questa tabella come consulenza legale.

### Modello dati IVMS 101

Lo standard del settore per i dati scambiati nell'ambito della Travel Rule è **IVMS 101** (interVASP Messaging Standard).
`travel_rule_details.originator_data` e `travel_rule_details.beneficiary_data` sono payload di persone in stile IVMS 101: Didit li inserisce nella busta nativa di ciascun canale. Il canale TRP scambia blocchi `IVMS101` (`ivms101.2023`, riportato nel campo `ivms_version` del trasferimento), il canale Sygna usa la sua variante IVMS cifrata con ECIES, e i canali `GTR`, `TRUST` e `VERIFYVASP` usano le proprie buste cifrate. Così una sola struttura del payload raggiunge ogni controparte nel formato previsto dal suo protocollo.

Quando costruisce il messaggio IVMS 101, Didit legge queste chiavi da ciascun payload di persona: `first_name` e `last_name` (oppure un singolo `name` o `full_name`), `date_of_birth`, `place_of_birth`, `residence_country` (oppure `country`), `vendor_data` (oppure `customer_identification`) e `wallet_address`.

Due regole pratiche:

* **Sistema di scrittura latino.** IVMS 101 richiede valori in sistema di scrittura latino, quindi traslittera i nomi scritti originariamente in un altro sistema di scrittura. Il [confronto dei nomi](#rigore-della-corrispondenza-dei-nomi) di Didit confronta insiemi di token normalizzati, perciò differenze di ordine e di maiuscole/minuscole non fanno fallire uno scambio, mentre sistemi di scrittura diversi sui due lati sì.
* **Invia dati che hai verificato.** Quando il soggetto indicato in `vendor_data` è un utente con una verifica KYC Didit approvata, Didit trasmette l'identità verificata, non i valori che hai digitato: vedi [Dati verificati e provenienza](#dati-verificati-e-provenienza).
  Per qualsiasi altro soggetto, Didit trasmette esattamente il `originator_data` che invii, quindi costruiscilo a partire dall'identità verificata in fase di onboarding e non da un campo di modulo non verificato.
  È ciò che richiede la formulazione della FATF "**richieste e accurate** informazioni sull'ordinante".
  Sul canale `INTERNAL`, anche l'applicazione del beneficiario riceve il `subject` che hai inviato (nome, `vendor_data`, data di nascita, paese e indirizzo) come controparte della sua transazione in entrata.

#### Dati verificati e provenienza

Quando il soggetto di un trasferimento è uno dei tuoi utenti, cioè una persona fisica con una verifica KYC approvata, Didit costruisce quel lato dello scambio a partire dai dati verificati:

* l'ordinante di un trasferimento in uscita che crei con `POST /v3/transactions/`;
* il beneficiario di un trasferimento in entrata che segnali con `POST /v3/transactions/`, oppure con `POST /v3/travel-rule/inbound/` quando `holder_vendor_data` del wallet abbinato indica quell'utente.

Con `POST /v3/transactions/`, entrambi i casi si applicano a una transazione il cui `transaction_category` è `travel_rule` mentre la Travel Rule è attiva.

Nome e cognome verificati, data e luogo di nascita, numero e tipo del documento, indirizzo e paese di residenza (ricavato da quell'indirizzo) hanno la precedenza sui valori che hai inviato. Un campo che la verifica non contiene mantiene il tuo valore, e così accade anche per un indirizzo completo che hai inviato quando quello verificato non è abbastanza completo da essere trasmesso.

Il `metadata` del trasferimento, nell'oggetto `travel_rule` incorporato nella transazione, registra la provenienza di ogni campo e i punti in cui i tuoi valori differivano:

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

`*_provenance` associa ogni campo a `verified` o `caller`, mentre `*_verified_differences` elenca ogni campo in cui hai inviato un valore diverso da quello verificato, ignorando maiuscole/minuscole, spaziature e codici paese di due o tre lettere. Mentre i dati di un trasferimento in entrata sono [mascherati](#dati-della-controparte-mascherati), le differenze non vengono incluse. Didit calcola entrambe queste chiavi, quindi le copie di queste chiavi, o di `name_match`, che invii in `travel_rule_details.metadata` vengono eliminate.

#### Invio diretto di IVMS 101

Oltre agli oggetti piatti `originator_data` e `beneficiary_data`, `travel_rule_details` (su `POST /v3/transactions/`) e `POST /v3/travel-rule/inbound/` accettano IVMS 101 nel formato standard:

* un blocco `originator` e un blocco `beneficiary`, con `originatorPersons` o `beneficiaryPersons` che contengono un `naturalPerson` oppure un `legalPerson`, e `accountNumber`;
* gli stessi blocchi all'interno di un oggetto `ivms101` (o `IVMS101`);
* una singola persona IVMS 101, oppure un intero blocco, come `originator_data` o `beneficiary_data`.

Ogni lato accetta una sola persona: un `naturalPerson` oppure un `legalPerson`, che rende la parte un'azienda. Un `originator_data` o `beneficiary_data` piatto e non vuoto prevale su un blocco per lo stesso lato.

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

Un blocco malformato restituisce `400` con il percorso come chiave, per esempio `{"travel_rule_details": {"originator.originatorPersons": ["must be a non-empty list of originator persons."]}}`. Su `POST /v3/travel-rule/inbound/` le stesse chiavi si trovano al livello superiore, sotto `ivms101.` quando usi il wrapper.

#### Dati richiesti per regime

Con la Travel Rule attiva, un trasferimento in uscita pari o superiore alla tua soglia deve contenere quanto richiesto dal suo regime, altrimenti restituisce `400`. Vengono controllati solo i lati che hai inviato, i dati verificati valgono per l'ordinante, e gli errori compaiono in `travel_rule_details.originator_data` o `travel_rule_details.beneficiary_data`, per esempio `"EU TFR requires the originator name."` o `"FATF Recommendation 16 requires the beneficiary wallet address."`:

| Regime | Ordinante | Beneficiario |
| - | - | - |
| EU TFR (la tua `jurisdiction` è uno Stato membro dell'UE, Islanda, Liechtenstein, Norvegia, `EU` o `EEA`; `EU` è il valore predefinito) | Il nome, insieme all'indirizzo, al numero del documento ufficiale e al numero di identificazione del cliente, oppure la data e il luogo di nascita. Un'azienda non ha un'alternativa basata sulla nascita. | Nome e indirizzo del wallet |
| FATF Recommendation 16 (ogni altra giurisdizione, compresa una giurisdizione vuota) | Il nome, insieme a uno tra indirizzo, numero del documento ufficiale o numero di identificazione del cliente, oppure la data e il luogo di nascita. Un'azienda non ha un'alternativa basata sulla nascita. | Nome e indirizzo del wallet |

Per l'ordinante, il controllo legge i campi che la tua applicazione condivide in [`data_sharing_fields`](#condivisione-dei-dati), perché sono tutti quelli che un canale trasmette; il beneficiario viene controllato così come lo hai inviato. Quando il trasferimento soddisfa il regime solo grazie a un campo che non condividi, il `400` indica il requisito del regime e poi i campi che le tue impostazioni condividono.

Il numero del documento ufficiale è `national_id` (oppure `document_number`), il numero di identificazione del cliente è `customer_identification` (oppure `vendor_data`), e la data di nascita è `date_of_birth`. Un `beneficiary_data.wallet_address` vuoto viene riempito con `counterparty.payment_method.account_id` prima del controllo, e un prelievo UTXO il cui output del beneficiario è stato dedotto da Didit a partire da `travel_rule_details.utxo` viene considerato come contenente tale indirizzo. Un trasferimento Lightning a cui la Travel Rule non si applica non viene controllato.

### Travel Address

Un **Travel Address** è una stringa compatta e codificata che punta all'endpoint di richiesta in entrata `TRP` di una VASP. Non espone mai un URL grezzo né alcun indirizzo wallet.
Dopo aver attivato la Travel Rule, Didit genera il tuo `travel_address` (restituito in sola lettura nelle impostazioni), così puoi condividerlo con le altre VASP che ti raggiungono tramite il canale `TRP`.
Ciascun wallet della tua rubrica degli indirizzi dei wallet riceve anche un `receiving_travel_address` specifico: una richiesta inviata a quell'indirizzo indica il wallet, quindi Didit non deve individuarlo tramite numero di conto o nome del titolare.
L'host TRP pubblico di Didit non risponde ancora alle altre VASP, quindi la ricezione tramite `TRP` non è disponibile finché non lo farà: vedi [reti Travel Rule](https://docs.didit.me/it/transaction-monitoring/travel-rule-networks.md).
Quando conosci il Travel Address di una controparte, salvalo nella [voce della rubrica degli indirizzi dei wallet](#rubrica-degli-indirizzi-wallet) di destinazione, così Didit instrada i trasferimenti di quel beneficiario direttamente tramite `TRP` invece di ricorrere all'email.
Didit valida i Travel Address che salvi in una voce della rubrica degli indirizzi wallet o invii in `originating_vasp`: ognuno deve iniziare con `ta` ed essere decodificabile in un URL di richiesta che contiene `t=i`, quindi un segnaposto come `ta...` restituisce `400`.
Un `beneficiary_data.travel_address` su una transazione non viene validato: se non si decodifica, il canale `TRP` viene saltato.

La codifica è Base58Check con prefisso `ta`: host e percorso dell'endpoint (che include sempre la coppia di query `t=i`), più un checksum double-SHA-256 di quattro byte, codificato in base58. Un Travel Address reale ha quindi questo aspetto e arriva a circa 100 caratteri:

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

Quando Didit valida un Travel Address, un valore che non è ben formato o il cui checksum non è valido restituisce `400` con `"Invalid travel address."`.
Usa un indirizzo reale dalla risposta relativa alle tue impostazioni o dalla controparte stessa.

## Test senza credenziali di rete

Non ti serve l'adesione a GTR, TRUST, VerifyVASP o Sygna per testare i percorsi che non richiedono adesione. Ti serve comunque una chiave API Didit per l'applicazione in test.

* **Sandbox in uscita:** invia una transazione `travelRule` da un'applicazione sandbox. Dopo i controlli sulla soglia e sui wallet in autocustodia, il [Test VASP di Didit](https://docs.didit.me/it/transaction-monitoring/travel-rule-sandbox.md) risponde all'interno di Didit con lo scenario che scegli in base al wallet o al nome del beneficiario: accettazione, rifiuto, mancata corrispondenza del nome, non raggiungibile, timeout o wallet in autocustodia. Nessuna rete, nessuna email e nessun altro cliente Didit riceve nulla.
* **Sandbox in entrata:** fai inviare al Test VASP un trasferimento verso di te con [Attiva trasferimento in entrata del Test VASP](https://docs.didit.me/it/management-api/travel-rule/trigger-test-vasp-inbound.md), oppure registrane uno tu stesso con [Registra trasferimento Travel Rule in entrata](https://docs.didit.me/it/management-api/travel-rule/register-inbound.md). Prova un wallet sconosciuto, un wallet non verificato, una mancata corrispondenza del nome del beneficiario e un wallet verificato e corrispondente. Questi scenari riproducono decisioni reali in entrata senza contattare alcuna rete.
* **Due applicazioni controllate in produzione:** usa il canale `INTERNAL` tra due tue applicazioni in ambiente di produzione (quella ricevente è rilevabile e dimostra il controllo del wallet di destinazione con un messaggio firmato o un deposito di prova), oppure una controparte TRP che controlli tu, per testare uno scambio a due parti senza credenziali commerciali di rete. Le applicazioni in produzione possono generare i normali addebiti e le normali notifiche; usa identità e controparti di test che controlli tu.

Vedi [Testare la Travel Rule in sandbox](https://docs.didit.me/it/transaction-monitoring/travel-rule-sandbox.md) per ogni scenario e il relativo esito esatto. I test sandbox o i test locali del protocollo riusciti non convalidano le credenziali, l'adesione o l'interoperabilità in produzione di una rete commerciale. Questi richiedono una sandbox di rete autorizzata oppure uno scambio controllato in produzione con credenziali di adesione valide.

## Invio di un trasferimento

Includi il trasferimento su [`POST /v3/transactions/`](https://docs.didit.me/it/transaction-monitoring/transactions) impostando `transaction_category` su `travelRule` (oppure `travel_rule`) e allegando un oggetto `travel_rule_details` (alias: `travelRule`).

Il blocco `travel_rule_details` è facoltativo, ma una volta allegato, `travel_rule_details.status` è obbligatorio: un blocco senza questo campo restituisce `400`.
Quando Travel Rule è **abilitata** per la tua applicazione, Didit ignora il valore `status` che invii e gestisce lo scambio da sola:

1. Se l'importo è inferiore alla tua `threshold_amount` configurata, il trasferimento si risolve immediatamente in `NOT_APPLICABLE` e non viene negoziato nulla.
2. Se il metodo di pagamento della controparte dichiara la destinazione come wallet in autocustodia (`payment_method.method_type: "unhosted_wallet"`), non viene tentato alcun canale: il trasferimento passa direttamente a `UNCONFIRMED_OWNERSHIP` e il widget di verifica della proprietà del wallet viene generato automaticamente (vedi [Wallet in autocustodia dichiarati](#wallet-in-autocustodia-dichiarati)).
3. Altrimenti i canali vengono eseguiti in ordine di priorità, e il primo in grado di raggiungere la controparte porta lo scambio:
   * `INTERNAL` - esattamente un altro cliente Didit possiede una prova con messaggio firmato o con deposito di test per `beneficiary_data.wallet_address`, creata dopo l'ultimo cambio di titolare del wallet. La tua applicazione non viene mai considerata, e quando il tuo utente finale ha scelto un membro della rete Didit nel [widget di verifica della proprietà del wallet](https://docs.didit.me/it/transaction-monitoring/wallet-ownership-widget.md), conta solo la prova di quel membro. L'applicazione di quel cliente è attiva (non sandbox), ha Travel Rule abilitata e `is_discoverable` impostato, ed è il VASP che indichi quando invii `counterparty_vasp_lei` o `counterparty_vasp_name`. Un wallet solo dichiarato dall'utente, provato con uno screenshot, non verificato o presente soltanto nella rubrica degli indirizzi non riceve mai nulla tramite `INTERNAL`.
   * `TRP` - l'asset del trasferimento ha una mappatura del Digital Token Identifier per la rete del trasferimento (vedi [Identificatori di asset TRP](#identificatori-di-asset-trp)), e il payload contiene `beneficiary_data.travel_address`, oppure la voce della rubrica degli indirizzi della destinazione ne memorizza uno, oppure la controparte si risolve nella [directory](#directory) (tramite `counterparty_vasp_lei` o `counterparty_vasp_name`) con un endpoint TRP.
   * `GTR`, `TRUST`, `VERIFYVASP`, `SYGNA` - hai collegato la tua adesione a quella rete in **Marketplace**, e la controparte si risolve in un ID di rete (campo esplicito o voce della directory - vedi [Campi di risoluzione della controparte](#campi-di-risoluzione-della-controparte)).
     Didit non dispone ancora di alcuna adesione alla piattaforma su queste reti (è in fase di onboarding come provider), quindi `disabled_networks` oggi non modifica questo passaggio.
   * `EMAIL` - è stato fornito `beneficiary_data.counterparty_vasp_email`, oppure `counterparty_vasp_name` si risolve in una voce della directory con un'email di compliance.
4. Se nessun canale riesce a risolvere la controparte, Didit esegue la catena di [scoperta della controparte](#scoperta-della-controparte). Con `vasp_attribution_enabled` attivo, questa include [attribuzione tramite blockchain analytics](#attribuzione-tramite-analisi-blockchain): il wallet di destinazione viene ricondotto al VASP proprietario, il nome attribuito viene scritto in `beneficiary_data.counterparty_vasp_name` (se vuoto) e nella [directory](#directory), e i canali vengono rieseguiti una volta - quindi un wallet attribuito a un VASP la cui voce nella directory contiene un endpoint TRP, un ID di rete o un'email di compliance viene instradato in questo secondo passaggio.
5. Se la controparte resta non risolta, il trasferimento passa a `COUNTERPARTY_VASP_NOT_FOUND`. Sui trasferimenti in uscita Didit genera automaticamente il [widget di verifica della proprietà del wallet](https://docs.didit.me/it/transaction-monitoring/wallet-ownership-widget.md) (quando `auto_wallet_verification` è attivo), così il trasferimento può comunque completarsi come trasferimento verso un wallet in autocustodia, e puoi rieseguire l'instradamento più tardi con `action: "resend"` quando avrai dati più accurati sulla controparte.

I passaggi 1 e 2 avvengono all'interno della richiesta. I passaggi da 3 a 5 vengono eseguiti subito dopo la risposta: il trasferimento torna con `AWAITING_COUNTERPARTY` e `protocol: null`, e ogni esito arriva come webhook [`travel_rule.status.updated`](#webhook).

### Identificatori di asset TRP

`TRP` identifica l'asset trasferito tramite il suo Digital Token Identifier (DTI) ISO 24165.
Un DTI identifica un token su una singola blockchain, quindi un token multi-chain ha un DTI per ogni rete.

Didit invia trasferimenti tramite `TRP` per questi asset:

| Asset | Rete | DTI |
| - | - | - |
| `BTC` | Bitcoin | `4H95J0R2X` |
| `ETH` | Ethereum | `X9J9K872S` |
| `USDC` | Ethereum | `CK9PW1MFH` |
| `USDC` | Celo | `2ZTG3NNVB` |
| `USDC` | Base | `CP6817N4B` |
| `USDC` | Optimism | `898NNTPZJ` |
| `USDC` | Arbitrum One | `4ZSZS1F4F` |
| `USDC` | Polygon PoS | `LS71LQK3L` |
| `USDC` | Avalanche C-Chain | `45J6XJX7H` |
| `USDC` | Solana | `5R3XFPZSM` |
| `USDC` | Plume | `N064ZKXDM` |

Gli identificatori `USDC` sono quelli che l'emittente del token pubblica nel suo white paper MiCA.

Per un token multi-chain, il trasferimento deve indicare la rete in `transaction_details.crypto_params.crypto_chain` (ad esempio `CELO`, `BASE`, `OP`, `ARB` o `POL`).
Senza una rete, o su una rete senza mappatura, il trasferimento non viene inviato tramite `TRP` e Didit prova i canali rimanenti: prima le reti di interoperabilità, poi l'email.

`USDT` non è ancora mappato.
Un token senza mappatura DTI, come lo stablecoin proprietario di un'azienda, richiede che il suo emittente registri un DTI presso l'autorità di registrazione ISO 24165, uno per token per blockchain.
Una volta che i DTI esistono, contatta il supporto Didit indicando ogni DTI, la sua blockchain e i decimali del token, e Didit aggiunge la mappatura.

Le richieste `TRP` in entrata che contengono un DTI associato alla singola rete vengono registrate con la valuta del token, l'importo nei decimali del token e la rete.

### Scoperta della controparte

Un trasferimento che contiene solo un indirizzo raggiunge comunque la sua controparte ogni volta che qualcuno riesce a identificarla.
Prima che un trasferimento in uscita venga dichiarato non instradabile, Didit verifica, in quest'ordine, e si ferma al primo passaggio che indica un VASP con un instradamento disponibile:

| Passaggio | Cosa fa |
| - | - |
| `internal_address_book` | Un altro cliente Didit ha dimostrato il controllo del wallet (una firma o un deposito di test), quindi il canale `INTERNAL` consegna a lui. Una voce della rubrica degli indirizzi non provata non conta mai. |
| `wallet_attribution` | L'attribuzione del wallet tramite blockchain analytics, abbinata a un VASP della directory con un instradamento disponibile. Un risultato memorizzato viene riutilizzato e addebitato una sola volta. Richiede `vasp_attribution_enabled`. |
| `network_lookup` | Una rete Travel Rule che risponde alla domanda "chi detiene questo indirizzo", quando la tua applicazione vi ha accesso. Al momento solo GTR la offre, ed è eseguita quando viene utilizzato il canale GTR per l'invio. Altrimenti il passaggio viene registrato come `skipped` con il motivo. |
| `customer_hint` | Il nome, il LEI o la giurisdizione della VASP che hai inviato in `beneficiary_data`, abbinati a una VASP della directory con un percorso disponibile. Un `travel_address` o un'email di compliance viene raggiunto tramite il proprio canale. |
| `end_user` | Nessuno ha indicato la controparte, quindi viene chiesto all'utente finale. Vedi sotto. |

Il campo `discovery` del trasferimento elenca ogni passaggio eseguito con il suo `outcome` (`match`, `miss` o `skipped`), un `reason` leggibile dalle macchine, il `vasp` e il `rail` trovati, e un timestamp.
Una VASP scelta da te o dall'utente finale prevale su ogni passaggio automatico: la discovery non la sostituisce mai con una propria ipotesi.

Quando nessun passaggio indica una controparte, il trasferimento passa a `COUNTERPARTY_VASP_NOT_FOUND`, oppure a `COUNTERPARTY_VASP_NOT_REACHABLE` quando è stata indicata una VASP ma nessuno dei suoi percorsi è disponibile per la tua applicazione.
Il trasferimento riporta quindi un `reason` (`awaiting_end_user`, `no_directory_match`, `directory_match_no_route`, oppure `picked_member_without_proven_wallet` quando il membro scelto dall'utente finale non ha dimostrato il possesso del wallet) e un elenco di `next_actions`:

| `action` | Significato |
| - | - |
| `select_counterparty_vasp` | L'utente finale sceglie la VASP di destinazione nel [widget del wallet](https://docs.didit.me/it/transaction-monitoring/wallet-ownership-widget.md), oppure la indichi tu stesso con `{"action": "beneficiary_vasp", "beneficiary_vasp": "<directory VASP id>"}` sull'[endpoint del trasferimento](#invio-di-un-trasferimento). Il trasferimento viene instradato verso quella VASP e inviato di nuovo. |
| `declare_self_hosted` | L'utente finale dichiara il wallet in autocustodia nello stesso widget. |
| `add_vasp_hint` | Invia un nome VASP, un LEI o un `travel_address` in `beneficiary_data`, quindi reinvia la richiesta. |
| `update_compliance_email` | Fornisci di nuovo l'email di compliance della controparte quando la prima è stata rifiutata; vedi [Perché un trasferimento è bloccato](#perché-un-trasferimento-è-bloccato). |
| `resend` | Esegui di nuovo la discovery con ciò che è cambiato. |

Il link del widget è `url` nelle azioni che l'utente finale esegue.
Quando un'azione di verifica della proprietà del wallet è in sospeso, il blocco `action_required` della transazione (tipo `wallet_ownership`) riporta lo stesso `reason` e gli stessi `next_actions`, così un client che già segue `action_required` mostra il selettore senza ulteriore lavoro.

### Campi di risoluzione della controparte

Tutto ciò che Didit sa sulla controparte proviene da `travel_rule_details.beneficiary_data`.
Questi campi determinano la risoluzione del canale; sono tutti facoltativi:

| Campo | Determina |
| - | - |
| `wallet_address` | La corrispondenza nella rubrica degli indirizzi `INTERNAL`, la ricerca nella rubrica degli indirizzi `TRP` e i flussi di verifica della proprietà del wallet. Se lo ometti, Didit usa `counterparty.payment_method.account_id`. |
| `chain` | Limita entrambe le ricerche nella rubrica degli indirizzi: una voce corrisponde solo se il suo `chain` è uguale a questo valore (senza distinzione tra maiuscole e minuscole) oppure se la voce non ha un `chain`. Se lo ometti, Didit lo compila a partire da `transaction_details.crypto_params.crypto_chain`, `custom_properties.crypto_chain` o dalla valuta del trasferimento, in maiuscolo, ma solo quando tale valore è una catena riconosciuta da Didit (ad esempio `ETH`, `BTC`, `SOL`, `TRX`); altrimenti il trasferimento non riporta alcuna catena e corrisponde a voci su qualsiasi catena. Per un trasferimento `USDT` o `USDC` senza catena esplicita, Didit la deduce da un hash di transazione in `transaction_details.payment_reference_id` (un hash `0x` indica `ETH`). |
| `memo` | Il destination tag o memo di `wallet_address` su una rete che li utilizza. Fa parte del wallet ovunque `wallet_address` venga confrontato (vedi [Reti con memo e tag](#reti-con-memo-e-tag)). Alias: `destinationTag`. |
| `travel_address` | Instrada direttamente tramite `TRP`: è il segnale più forte che tu possa fornire. |
| `counterparty_vasp_lei` | Ricerca nella directory tramite LEI per `TRP`, `GTR`, `TRUST`, `VERIFYVASP` e `SYGNA`. Viene anche verificato incrociando l'identità riportata dall'endpoint TRP: una discordanza, oppure un'identità senza LEI, interrompe lo scambio con `COUNTERPARTY_VASP_NOT_REACHABLE`. |
| `counterparty_vasp_name` | Ricerca nella directory per `TRP`, `GTR`, `TRUST`, `VERIFYVASP`, `SYGNA` e `EMAIL`: prima il nome esatto, poi lo stesso nome scritto in altro modo (`B.V.` per `BV`, un accento), quindi un alias di una voce. Quando sono presenti entrambi, viene verificato in modo approssimato rispetto all'identità TRP. |
| `counterparty_vasp_jurisdiction` | Codice paese ISO 3166 dell'entità ricevente quando la VASP indicata è un brand con più entità regolamentate, oppure quando più voci della directory condividono il nome (vedi [Brand e le loro entità](#brand-e-relative-entità)). |
| `counterparty_gtr_vasp_code` | ID di rete `GTR` esplicito: salta la directory. |
| `counterparty_trust_membership_id` | ID di rete `TRUST` esplicito: salta la directory. |
| `counterparty_verifyvasp_id` | ID di rete `VerifyVASP` esplicito: salta la directory. |
| `counterparty_sygna_vasp_code` | Codice VASP esplicito di `Sygna Bridge`: salta la directory. |
| `counterparty_vasp_email` | Contatto di compliance esplicito per il canale `EMAIL`: salta la directory. |

### Forme delle catene

Su una catena basata su account (catene EVM, Solana, Tron) un trasferimento sposta fondi da un indirizzo a un altro, e Didit legge entrambi i wallet direttamente dalla transazione.
Per altre tre forme servono informazioni aggiuntive, e i dati che Didit ha risolto per queste forme sono riportati nel trasferimento come `chain_details` (vuoto, `{}`, su una catena basata su account).
`chain_details.originator` e `chain_details.beneficiary` riportano ciascuno l'`address`, il suo `memo` e la `source` da cui proviene, e la corrispondenza e l'instradamento leggono prima da lì i wallet.

#### Trasferimenti UTXO

Una transazione Bitcoin, Litecoin, Bitcoin Cash o Dogecoin spende input provenienti da un numero qualsiasi di indirizzi e paga un numero qualsiasi di output, alcuni dei quali restituiscono il resto al mittente.
Invia input e output come `travel_rule_details.utxo` (importi nell'unità propria della moneta, come stringhe decimali), e Didit deduce ciò che non dichiari:

* **Ordinante**: `originator_data.wallet_address` quando lo invii, altrimenti l'indirizzo di input che ha contribuito di più (`source: largest_input`).
* **Beneficiario**: il wallet dichiarato, altrimenti l'unico output che non restituisce un resto a un indirizzo di input (`only_non_change_output`), altrimenti l'unico output che paga l'importo del trasferimento (`amount_match`).

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

Il trasferimento porta quindi con sé:

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

`chain_details.warnings` segnala le incongruenze: `declared_originator_not_an_input`, `declared_beneficiary_not_an_output`, `beneficiary_output_ambiguous` (nessun singolo output poteva essere distinto dagli altri) e `beneficiary_output_amount_differs`.
`utxo` su qualsiasi altra catena restituisce `400`, e ciascuna lista contiene al massimo 1.000 voci.
Un deposito segnalato usa lo stesso oggetto `utxo` (vedi [Registrazione sunrise dopo il deposito](#registrazione-postuma-del-deposito-sunrise)).

#### Reti con memo e tag

Su XRP, Stellar (XLM), EOS, Cosmos (ATOM) e Hedera (HBAR) un exchange riceve tutti i propri clienti su un unico indirizzo condiviso e li distingue tramite il destination tag o il memo.
Il memo fa quindi parte del wallet: invialo come `payment_method.memo` sul partecipante, oppure come `memo` in `originator_data` / `beneficiary_data` (alias `destinationTag`), e Didit confronta insieme indirizzo e memo.

* Una voce della rubrica degli indirizzi con un memo corrisponde solo ai trasferimenti che indicano quel memo. Una voce senza memo corrisponde a tutto l'indirizzo. Un trasferimento che non indica alcun memo non raggiunge mai una voce che ne ha uno: su un indirizzo condiviso, un deposito senza il suo tag non appartiene a nessuno.
* Un X-address di XRP contiene al proprio interno il tag: Didit lo separa nell'indirizzo classico e nel tag (`source: x_address`), quindi un wallet registrato in una delle due forme corrisponde a un trasferimento nell'altra.
* Ogni memo su un indirizzo condiviso è un metodo di pagamento a sé stante nella transazione.
* Cosa accetta ciascuna rete: un destination tag XRP è un numero intero da 0 a 4294967295 (è accettato un numero JSON); un memo Stellar è un testo fino a 28 byte, un ID a 64 bit o un hash a 32 byte in esadecimale; EOS accetta fino a 256 byte, Cosmos fino a 256 caratteri, Hedera fino a 100 byte. Un memo su una catena che non lo prevede (Bitcoin, catene EVM, Solana, Tron, Litecoin, Bitcoin Cash, Dogecoin, Lightning) restituisce `400`.

#### Lightning

Un pagamento Lightning non ha un indirizzo beneficiario on-chain: il pagatore detiene una richiesta di pagamento.
Su un trasferimento crypto su Bitcoin o Lightning, `payment_method.account_id` può contenere quella richiesta, e Didit identifica il beneficiario a partire da essa senza contattare alcuna rete:

| Cosa invii | Beneficiario |
| - | - |
| Fattura BOLT11 (`lnbc...`) | Il nodo beneficiario del pagamento, indicato nella fattura o ricavato dalla sua firma. |
| Offerta o fattura BOLT12 (`lno1...`, `lni1...`) | Il nodo emittente, a meno che non si nasconda dietro percorsi offuscati (blinded paths). |
| Lightning Address (`name@domain`) | L'indirizzo stesso. |
| ID del nodo | Il nodo stesso. |
| LNURL (`lnurl1...`, `lnurlp://`) | Nessuno: indica un servizio, non un beneficiario. |

Il beneficiario viene memorizzato come account e come `chain_details.beneficiary` (`source: invoice_payee`), sulla catena `LIGHTNING`, mentre ciò che dichiara la richiesta è in `chain_details.lightning`.
Quando la richiesta non indica alcun beneficiario, un trasferimento in uscita assume lo stato `NOT_APPLICABLE`, con il motivo in `chain_details.not_applicable_reason` e nel suo `timeline`: `LIGHTNING_NO_PAYEE_IDENTIFIER`, `LIGHTNING_BOLT12_BLINDED_PAYEE` oppure `LIGHTNING_LNURL_NAMES_NO_PAYEE`.
Un valore viene interpretato come Lightning solo su bitcoin, su `LIGHTNING`, oppure quando non è indicata alcuna catena (un Lightning Address solo su bitcoin o `LIGHTNING`): su qualsiasi altra catena è l'indirizzo proprio di quella catena.

> [!NOTE]
>
> Il rail `INTERNAL` raggiunge un altro cliente Didit solo tramite un wallet che tale cliente ha dimostrato di controllare con un messaggio firmato o un deposito di prova, e tali prove oggi esistono per Bitcoin, catene EVM, Solana e Tron.
> Sulle reti con memo, su Lightning, Litecoin, Bitcoin Cash e Dogecoin, un trasferimento quindi non raggiunge mai un altro cliente Didit tramite `INTERNAL`.
> Il confronto di memo, tag e Lightning continua però a valere per la tua rubrica degli indirizzi: trasferimenti in entrata, depositi segnalati e richieste `TRP` verso i tuoi wallet.

### Aggiornare il wallet dell'ordinante

Un prelievo viene spesso dichiarato dal wallet principale del cliente e trasmesso dagli indirizzi che detenevano effettivamente le monete.
Registra il wallet da cui i fondi sono effettivamente usciti con `PATCH /v3/transactions/{transaction_id}/travel-rule/`:

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

* Solo per i trasferimenti in uscita, e mai per uno in stato `CANCELLED` o `EXPIRED` (`409`).
* Quando gli input UTXO del trasferimento sono noti, il wallet deve essere uno di essi (altrimenti `400`). Invia anche `memo` su una rete con memo.
* Modifica solo il record: nulla viene inviato di nuovo alla controparte e lo stato resta invariato. `chain_details.originator` diventa il nuovo wallet con `source: updated`, il `timeline` registra il wallet precedente e quello nuovo, e la controparte `INTERNAL` del trasferimento viene aggiornata allo stesso modo.

### Attribuzione tramite analisi blockchain

Quando passi solo l'indirizzo di un wallet, Didit può comunque stabilire chi si trova dall'altra parte.
Se nessun rail può instradare il trasferimento, Didit risolve il wallet di destinazione tramite i dati di attribuzione dell'analisi blockchain: la stessa analisi che alimenta lo [screening delle transazioni crypto](https://docs.didit.me/it/transaction-monitoring/aml-screening.md) sa quali wallet appartengono a quali exchange e custodi.
L'attribuzione viene eseguita solo sui trasferimenti in uscita che riportano sia un wallet di destinazione sia una `chain` (vedi [Campi di risoluzione della controparte](#campi-di-risoluzione-della-controparte)); senza una catena viene saltata.

Quando il wallet è attribuito a un'entità nota, Didit:

1. Registra l'attribuzione sul trasferimento: `beneficiary_data.counterparty_vasp_name` viene compilato (se non l'hai fornito tu), e i metadati del trasferimento contengono un blocco `vasp_attribution` con nome dell'entità, tipo di entità, paese e `source: "blockchain_analytics"`.
2. Aggiunge l'entità alla [directory dei VASP](#directory) (oppure ne abbina una voce esistente), così l'attribuzione resta stabile tra un trasferimento e l'altro.
3. Riesegue una sola volta i rail con il nome attribuito: una voce della directory che già possiede un endpoint TRP fa sì che il trasferimento venga instradato subito, invece di finire in `COUNTERPARTY_VASP_NOT_FOUND`.

La chiamata di attribuzione funge anche da screening crypto completo: la transazione riceve l'intero output dello screening (punteggio di rischio, categoria di rischio del wallet, snapshot della rete), esattamente come se il monitoraggio crypto fosse stato eseguito, e `custom_values.aml_screening_trigger` della transazione viene impostato a `travel_rule_attribution`, così puoi vedere che lo screening è stato eseguito perché richiesto dall'instradamento Travel Rule.
Quando il monitoraggio crypto ha già sottoposto a screening lo stesso wallet per questa transazione, viene riutilizzato il risultato memorizzato: nessuna seconda chiamata all'analisi, nessun secondo addebito.
L'attribuzione non blocca mai la creazione della transazione: se la ricerca tramite l'analisi fallisce o il tuo saldo non è sufficiente a coprirla, il trasferimento prosegue semplicemente verso `COUNTERPARTY_VASP_NOT_FOUND` e il tentativo non viene addebitato.
Con `action: "resend"`, un'attribuzione già registrata viene riutilizzata invece di essere richiesta di nuovo.

Disattiva l'intero passaggio con `vasp_attribution_enabled: false` nelle [impostazioni](#configurazione).
Consulta [Prezzi](#prezzi) per sapere come viene fatturata la chiamata di attribuzione.

Quando Travel Rule è **disattivato**, `travel_rule_details` (incluso uno `status` fornito dal chiamante, legacy o attuale) viene comunque registrato sulla transazione, ma in modo passivo - non viene attivato nessun rail.
Usalo per integrare retroattivamente i dati di compliance che hai già tracciato con il tuo processo.
Un trasferimento passivo in uscita non avvia alcuno scambio, quindi viene fatturato come Screening delle transazioni, non sulla [voce Travel Rule](#prezzi).

Con Travel Rule attivo, questa richiesta passa tramite il rail `EMAIL`, perché indica l'email di compliance della controparte e nessun rail precedente può raggiungere il beneficiario:

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

La risposta, abbreviata ai campi rilevanti qui:

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

* `originator_data` è quello che hai inviato, perché il soggetto dell'esempio non ha una verifica KYC approvata; per un utente verificato Didit lo costruisce a partire dai dati verificati (vedi [Dati verificati e provenienza](#dati-verificati-e-provenienza)).
  Il rail `EMAIL` mostra al destinatario solo i campi dell'ordinante che condividi in [`data_sharing_fields`](#condivisione-dei-dati).
* `beneficiary_data.chain` è `ETH` perché la richiesta non indicava alcuna chain, quindi Didit l'ha ricavata dalla valuta.
* `status` è `APPROVED` perché nessuna regola ha agito sulla transazione; le tue regole possono impostare un altro stato.
* Il contatto di compliance riceve il link di ritiro e il trasferimento si completa, non supera il controllo del nome o viene rifiutato quando risponde, oppure scade se non risponde (vedi [Ritiro via email](#invio-via-email-alle-controparti-non-raggiungibili)).

`protocol` resta `null` perché il rail viene scelto dopo la risposta (ad esempio `EMAIL` quando fornisci `counterparty_vasp_email`): [Ottieni una transazione](https://docs.didit.me/it/management-api/transactions/get.md) lo mostra una volta scelto, e ogni successivo webhook `travel_rule.status.updated` lo riporta in `rail`.
Se il wallet del beneficiario appartiene a un altro cliente Didit che ne ha dimostrato il controllo, il rail `INTERNAL` regola l'intero scambio subito dopo la risposta, e quel webhook riporta già `COMPLETED` (oppure `COUNTERPARTY_MISMATCHED_DATA`). Quando il nome non corrisponde, il tuo trasferimento è `COUNTERPARTY_MISMATCHED_DATA` e l'altro cliente non riceve nulla.
Senza `counterparty_vasp_email`, e quando né i rail né l'[attribuzione](#attribuzione-tramite-analisi-blockchain) possono raggiungere il beneficiario, il trasferimento termina più tardi in `COUNTERPARTY_VASP_NOT_FOUND` con un'azione `wallet_ownership` sulla transazione.

> [!NOTE]
>
> L'oggetto `travel_rule` incorporato nella transazione contiene i campi propri del trasferimento (`uuid`, `status`, `protocol`, `required`, `obligations_count`, `originator_data`, `beneficiary_data`, `metadata`), ciò che Didit ha risolto e confrontato (`chain_details`, `name_match`, `data_match`, `mismatched_fields`, e i campi di [mascheramento](#dati-della-controparte-mascherati) `data_masked` e `data_unmasked`), e i campi che indicano a che punto si trova: `direction`, `rail`, `counterparty_vasp`, `delivery`, `discovery`, `reason` e `next_actions` (vedi [Perché un trasferimento è bloccato](#perché-un-trasferimento-è-bloccato)).
> Ogni riga di [`GET /v3/transactions/`](https://docs.didit.me/it/management-api/transactions/list) contiene lo stesso blocco, oppure `null` per una transazione senza trasferimento.
> Gli endpoint dedicati ai trasferimenti riportati sotto restituiscono anche questi campi, più `ivms_version`, `ownership_confirmed`, `deadline_at`, `timeline` e `created_at`, ma non `obligations_count` né `metadata`.

Per chiudere un trasferimento **in uscita** in stato `COMPLETED` dopo averlo trasmesso on-chain:

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

Questo richiede che il trasferimento sia un trasferimento **in uscita** in stato `COMPLETED`; altrimenti l'API restituisce `409`.
In caso di successo, sia il trasferimento in uscita sia la sua controparte sul rail `INTERNAL` passano a `FINISHED`, e il `payment_txn_id` della transazione viene impostato sull'hash che hai fornito.
Sul rail `TRP`, Didit invia inoltre l'hash al callback di conferma della controparte.

Per annullare un trasferimento che non ha ancora raggiunto uno stato finale, invia `{"action": "cancel"}` allo stesso endpoint.
Anche la copia sul rail `INTERNAL` viene annullata e, sul rail `TRP`, una volta che la controparte ha approvato la richiesta, Didit invia l'annullamento al suo callback di conferma.
Un trasferimento già in `FINISHED`, `CANCELLED` o `EXPIRED` restituisce `409`.
Una richiesta senza né `payment_txn_id` né un `action` supportato restituisce `400`.

Su un trasferimento inviato tramite `GTR`, `VERIFYVASP` o `SYGNA`, Didit comunica l'hash on-chain (o l'annullamento) alla rete dopo la risposta, con gli [stessi nuovi tentativi](#consegna-e-nuovi-tentativi); il campo `delivery` della risposta mostra quel messaggio.

Per ritentare un trasferimento in uscita che non ha potuto raggiungere la sua controparte, cioè uno che si trova in `COUNTERPARTY_VASP_NOT_FOUND`, `COUNTERPARTY_VASP_NOT_REACHABLE` o `NOT_ENOUGH_COUNTERPARTY_DATA`, migliora prima i dati della controparte, ad esempio aggiungendo un `travel_address` alla voce del wallet di destinazione, un [contatto](#contatti) per la voce della controparte nella directory, oppure catalogando il VASP nella [directory](#directory).
Poi invia `{"action": "resend"}` allo stesso endpoint.
Didit riavvia il termine per la conferma e rimette in coda la sequenza di instradamento dall'inizio, usando i dati memorizzati sul trasferimento: la risposta mostra nuovamente il trasferimento in `AWAITING_COUNTERPARTY` (con `resend queued` nella sua `timeline`) e l'esito arriva come webhook `travel_rule.status.updated`.
Un nuovo invio effettuato mentre un tentativo precedente è ancora in corso viene eseguito quando quel tentativo si conclude.
Qualsiasi altro stato, o un trasferimento in entrata, restituisce `409`.

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

Per indicare tu la controparte quando la [discovery](#scoperta-della-controparte) non è riuscita, invia `{"action": "beneficiary_vasp", "beneficiary_vasp": "<directory VASP id>"}` (il `id` di `GET /v3/travel-rule/vasps/`).
Il trasferimento viene instradato verso quel VASP e inviato di nuovo.
Solo un trasferimento in uscita in `COUNTERPARTY_VASP_NOT_FOUND`, `COUNTERPARTY_VASP_NOT_REACHABLE` o `NOT_ENOUGH_COUNTERPARTY_DATA` accetta questa azione; qualsiasi altro stato restituisce `409`, e un id sconosciuto restituisce `404`.

### Perché un trasferimento è bloccato

Un trasferimento in `COUNTERPARTY_VASP_NOT_FOUND` o `COUNTERPARTY_VASP_NOT_REACHABLE` indica il motivo per cui è bloccato e cosa lo fa avanzare, in ogni lettura della sua transazione.
L'oggetto `travel_rule` di [`GET /v3/transactions/{transaction_id}/`](https://docs.didit.me/it/management-api/transactions/get), del `201` di [`POST /v3/transactions/`](https://docs.didit.me/it/management-api/transactions/create) e di ogni riga di [`GET /v3/transactions/`](https://docs.didit.me/it/management-api/transactions/list) lo contiene, e lo contiene anche l'oggetto del trasferimento restituito dall'[endpoint del trasferimento](https://docs.didit.me/it/management-api/travel-rule/update-transfer.md):

* `reason` è la causa leggibile dalla macchina, `""` per qualsiasi altro stato.
* `next_actions` elenca ciò che fa avanzare il trasferimento, `[]` per qualsiasi altro stato.
* `delivery` è il messaggio più recente che il trasferimento deve inviare alla controparte: `kind`, `status` (`QUEUED`, `SENDING`, `RETRYING`, `DELIVERED` o `FAILED`), `rail`, `attempts`, `last_error`, `next_attempt_at` e `delivered_at`, oppure `null` quando non ne deve alcuno.
* `discovery` indica dove Didit ha cercato la controparte, con una voce per ogni passaggio eseguito: `step`, `outcome` (`match`, `miss` o `skipped`), `reason`, `vasp`, `rail` e `at`.

`email_undeliverable` e `delivery_failed` provengono da una consegna fallita e compaiono solo su `COUNTERPARTY_VASP_NOT_REACHABLE`.
Una consegna fallita determina prima `reason`, quindi una controparte che Didit ha trovato non viene mai segnalata come non trovata.
Gli altri quattro provengono dalla traccia di ricerca, in entrambi gli stati.

| `reason` | Cosa è successo | `next_actions` |
| - | - | - |
| `email_undeliverable` | Il provider di posta ha rifiutato l'email di compliance e non resta alcun indirizzo da provare: al momento dell'invio, in un sollecito o come bounce permanente segnalato in seguito. | `update_compliance_email`, poi `resend` |
| `delivery_failed` | Il rail che stava effettuando la consegna è fallito in modo definitivo: un rail di rete ha rifiutato il messaggio o ha esaurito i nuovi tentativi, un host di identità `TRP` non ha risposto, oppure l'host `TRP` della controparte non ha accettato la richiesta. | `resend` |
| `awaiting_end_user` | Nessun passaggio di ricerca ha indicato una controparte raggiungibile da Didit, quindi all'utente finale viene chiesto di indicarla. | `select_counterparty_vasp`, `declare_self_hosted`, `add_vasp_hint`, `resend` |
| `directory_match_no_route` | Un passaggio ha indicato una voce della [directory](#directory), ma quella voce non ha un percorso che Didit possa usare per te. | Come `awaiting_end_user` |
| `picked_member_without_proven_wallet` | L'utente finale ha scelto come controparte un altro cliente di Didit, ma tale cliente non ha dimostrato il controllo del wallet. | Come `awaiting_end_user` |
| `no_directory_match` | La traccia di ricerca non fornisce altri motivi. | Come `awaiting_end_user` |

| Azione successiva | Cosa fare |
| - | - |
| `update_compliance_email` | Fornisci di nuovo l'email di compliance della controparte, con `{"action": "update_compliance_email", "compliance_email": "..."}` sull'endpoint del trasferimento. |
| `resend` | Rilancia l'instradamento con `{"action": "resend"}` quando qualcosa è cambiato. |
| `select_counterparty_vasp` | L'utente finale sceglie il VASP di destinazione nel [widget di verifica della proprietà del wallet](https://docs.didit.me/it/transaction-monitoring/wallet-ownership-widget.md). `url` è il link al widget finché il trasferimento ha una sessione widget aperta. |
| `declare_self_hosted` | L'utente finale dichiara nel widget che il wallet è autocustodito, allo stesso `url`. |
| `add_vasp_hint` | Indica a Didit chi è la controparte, con il nome di un VASP, un LEI o un Travel Address (ad esempio un `travel_address` sulla [voce della rubrica degli indirizzi](#rubrica-degli-indirizzi-wallet) del wallet di destinazione), poi rilancia. |

Un nuovo invio fa avanzare il trasferimento, quindi il suo `reason` viene azzerato.
La voce della cronologia di una transizione causata da una consegna fallita riporta lo stesso valore in `reason`.

Se il provider di posta rifiuta l'email di compliance del [trasferimento di esempio sopra](#invio-di-un-trasferimento), il blocco `travel_rule` della sua transazione, in forma abbreviata, riporta:

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

Qui `delivery` concorda con `reason`, perché l'invio stesso è stato rifiutato.
Un rifiuto su un sollecito, o un bounce segnalato più tardi, lascia `delivery.status` su `DELIVERED`: la prima email è stata effettivamente inviata.
Per sapere perché un trasferimento è bloccato, leggi `reason`, non `delivery`.

Per risolvere, fornisci di nuovo l'email di compliance della controparte, poi rilancia:

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

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

`update_compliance_email` salva l'indirizzo come `beneficiary_data.counterparty_vasp_email` di questo trasferimento: appartiene solo a questo trasferimento e non entra in nessuna voce della directory né in nessun elenco di contatti.
Lo stato non cambia, la cronologia si arricchisce di `compliance email updated` e il trasferimento mantiene `reason: email_undeliverable` finché il nuovo invio non spedisce la richiesta al nuovo indirizzo.
Lo accetta solo un trasferimento in uscita in `COUNTERPARTY_VASP_NOT_FOUND`, `COUNTERPARTY_VASP_NOT_REACHABLE` o `NOT_ENOUGH_COUNTERPARTY_DATA`; ogni altro trasferimento riceve `409`, e viene restituito `400` se `compliance_email` manca o è malformato.

### Wallet in autocustodia dichiarati

Quando il tuo cliente ti comunica che la destinazione è un proprio wallet in autocustodia (non custodito), dichiaralo sulla transazione invece di lasciare che l'instradamento scopra che non c'è alcun VASP dietro: imposta il tipo di metodo di pagamento della controparte su `unhosted_wallet`.

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

La dichiarazione salta del tutto l'instradamento:

* Non viene tentato nessun rail: non c'è un VASP della controparte con cui scambiare dati. Il trasferimento viene creato direttamente in `UNCONFIRMED_OWNERSHIP`.
* Quando `auto_wallet_verification` è attivo (impostazione predefinita), Didit genera automaticamente una sessione del [widget di verifica della proprietà del wallet](https://docs.didit.me/it/transaction-monitoring/wallet-ownership-widget.md) collegata alla transazione e la restituisce nel blocco `action_required` della transazione; gli SDK la avviano automaticamente all'[invio lato client](https://docs.didit.me/it/transaction-monitoring/sdk-transaction-submission.md).
* Quando il cliente dimostra il controllo del wallet, il trasferimento esegue il confronto del nome del beneficiario e passa a `COMPLETED` (oppure a `COUNTERPARTY_MISMATCHED_DATA` se il confronto fallisce).

Questo è l'obbligo del regolamento TFR UE sui wallet in autocustodia in forma di API: verificare la proprietà del wallet non custodito invece di scambiare dati con un VASP della controparte.
La dichiarazione viene letta dal metodo di pagamento sul lato **destinazione** di un trasferimento in uscita e sul lato **origine** di uno in entrata: in entrambi i casi, il partecipante controparte.
Un trasferimento con wallet non custodito dichiarato segue già il suo percorso finale senza rail, quindi `UNCONFIRMED_OWNERSHIP` non è uno stato da reinviare: completa la prova di proprietà (oppure annulla) invece di chiamare `action: "resend"`.

## Ricezione

### Conferma dell'assetto proprietario del wallet

Un trasferimento resta in `UNCONFIRMED_OWNERSHIP` in due casi:

* Un trasferimento in entrata viene associato a una voce della [rubrica degli indirizzi](#rubrica-degli-indirizzi-wallet) il cui assetto proprietario non è ancora verificato.
* Il wallet della controparte è stato dichiarato in autocustodia (`counterparty.payment_method.method_type: "unhosted_wallet"`), in un prelievo in uscita o in un deposito in entrata. Vedi [Wallet in autocustodia dichiarati](#wallet-in-autocustodia-dichiarati).

La tua applicazione conferma o rifiuta il trasferimento:

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

Il corpo accetta `confirmed` (obbligatorio, booleano) e un `wallet_address` facoltativo.

L'endpoint accetta un trasferimento in uno qualsiasi di questi stati e restituisce `409` con `{"detail": "Transfer is not awaiting ownership confirmation."}` per qualsiasi altro stato:

* `UNCONFIRMED_OWNERSHIP`, in entrambe le direzioni.
* `ON_HOLD` su un trasferimento in entrata.
* `UNCONFIRMED_OWNERSHIP`, `ON_HOLD` o `COUNTERPARTY_MISMATCHED_DATA` su un trasferimento `TRP` in entrata, così un responsabile della compliance può risolvere manualmente una richiesta della controparte.

Su un trasferimento creato da Didit stessa (rail `INTERNAL`, registrazione sunrise o wallet in autocustodia dichiarato):

* `confirmed: true` contrassegna la voce della rubrica dei wallet corrispondente come con assetto proprietario verificato, poi esegue il confronto dei nomi con il `holder_name` di quella voce: `COMPLETED` se il confronto va a buon fine, `COUNTERPARTY_MISMATCHED_DATA` se non va a buon fine.
  La controparte sulla rail `INTERNAL`, quando esiste, riceve lo stesso esito.
  Per un wallet in autocustodia dichiarato, `confirmed: true` registra che il tuo cliente ha verificato chi controlla il wallet della controparte e completa il trasferimento (`COMPLETED`), in uscita o in entrata.
  Un trasferimento in entrata il cui deposito è già regolato passa direttamente a `FINISHED`.
* `confirmed: false` porta entrambi i lati del trasferimento a `COUNTERPARTY_VASP_GENERAL_DECLINE`.
* La voce corrispondente viene cercata nella tua rubrica degli indirizzi solo in base all'indirizzo, senza considerare la catena.
  Risolvere un `ON_HOLD` in entrata senza una voce corrispondente crea la voce a partire da `beneficiary_data.wallet_address` del trasferimento e la contrassegna come verificata.
  Un wallet in autocustodia dichiarato fa eccezione: il wallet viene registrato nella tua rubrica degli indirizzi come con assetto proprietario verificato, come descritto più sotto.
  In tutti gli altri casi, una voce mancante restituisce `409` con `{"detail": "wallet address entry no longer available"}`, che è anche la risposta a una voce eliminata.

Su un trasferimento `TRP` in entrata, la stessa chiamata risponde alla richiesta della controparte:

* `confirmed: true` richiede un indirizzo di pagamento da restituire, preso dal `wallet_address` della richiesta, poi dalla voce abbinata, poi da `beneficiary_data.wallet_address`.
  Se non ce n'è nessuno dei tre, la richiesta restituisce `400` con `{"wallet_address": ["wallet_address is required to approve."]}`.
  Didit crea o verifica la voce, invia alla controparte il callback di risoluzione della richiesta, imposta `ownership_confirmed` e porta il trasferimento a `COMPLETED`.
* `confirmed: false` invia una risoluzione di rifiuto e porta il trasferimento a `COUNTERPARTY_VASP_GENERAL_DECLINE`.
* Se l'endpoint di callback della controparte non è raggiungibile, la richiesta restituisce `502` e il trasferimento mantiene lo stato attuale.
  In caso di approvazione, la voce del wallet viene comunque creata o contrassegnata come verificata.

Per un wallet in autocustodia dichiarato, il wallet che verifichi è quello della controparte: la destinazione di un prelievo in uscita oppure l'origine (il wallet dell'ordinante) di un deposito in entrata.
Didit lo aggiunge alla rubrica dei wallet come con assetto proprietario verificato a nome della controparte, quindi il wallet viene confrontato con il nome della controparte (dell'ordinante, per un deposito).
Se la rubrica contiene già quel wallet con un nome del titolare diverso, il trasferimento passa invece a `COUNTERPARTY_MISMATCHED_DATA`.

Se il trasferimento non indica affatto un wallet della controparte, passa `wallet_address` nel corpo della richiesta.
Quando né il trasferimento né la richiesta forniscono un indirizzo, la richiesta viene rifiutata con `400`.

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

* Un trasferimento su rete a cui è già stata fornita una risposta sulla rete (un trasferimento VerifyVASP, oppure un trasferimento GTR o Sygna Bridge già deciso) restituisce `409` (vedi [Trasferimenti da una rete](#trasferimenti-da-una-rete)).

La risposta è l'oggetto del trasferimento più completo descritto sopra.
Un nuovo trasferimento `INTERNAL` non resta mai in attesa qui: raggiunge solo un cliente che ha già dimostrato il controllo del wallet. Un trasferimento `INTERNAL` più vecchio ancora in attesa da prima di questa regola mantiene nascosti i dati del mittente finché non dimostri il controllo del wallet (un messaggio firmato o un deposito di prova), e confermarlo restituisce `409` fino a quel momento. Rifiutarlo funziona ancora.
Quando la controparte ha risposto che il wallet è in autocustodia (oggi il [Didit Test VASP](https://docs.didit.me/it/transaction-monitoring/travel-rule-sandbox.md) fornisce questa risposta in sandbox), la conferma aggiunge il wallet alla tua rubrica degli indirizzi a nome del beneficiario ed esegue il confronto dei nomi: se il confronto va a buon fine, il trasferimento si completa e il wallet viene contrassegnato come verificato.

### Trasferimenti da una rete

Didit può ricevere anche trasferimenti Travel Rule che una controparte invia tramite `GTR`, `VERIFYVASP` o `SYGNA`.
La ricezione viene attivata da Didit separatamente per ogni rete, e **oggi nessuna è attiva**: richiede anche la registrazione degli endpoint di Didit presso ciascuna rete, e Didit non è ancora membro di queste reti.
I trasferimenti `TRUST` non possono essere ricevuti.

Quando una rete è attiva, un messaggio da essa consegnato viene gestito così:

* **Instradamento.** Il messaggio arriva alla tua applicazione quando indica il codice partecipante della tua appartenenza connessa su quella rete. Un messaggio indirizzato all'appartenenza di Didit arriva a te solo se sei l'unico cliente Didit attivo che ha dimostrato il controllo del wallet del beneficiario. Qualsiasi altro messaggio viene rifiutato, così nessun cliente riceve mai il trasferimento di un altro cliente.
* **Decisione.** Didit crea il trasferimento in entrata nella tua applicazione e lo decide come una [richiesta TRP](https://docs.didit.me/it/transaction-monitoring/travel-rule-interoperability.md#endpoint-trp): confronto del wallet, assetto proprietario, confronto dei nomi e `inbound_auto_accept`.
* **Una sola volta.** Le reti reinviano un messaggio finché non riceve risposta. Un duplicato riceve la stessa risposta della prima copia, e nulla viene creato o deciso due volte.
* **La tua revisione, su `GTR` e `SYGNA`.** Un trasferimento che attende te (`UNCONFIRMED_OWNERSHIP`, `ON_HOLD` o `COUNTERPARTY_MISMATCHED_DATA`) si decide con [`POST .../travel-rule/ownership/`](#conferma-dell’assetto-proprietario-del-wallet): `confirmed: true` lo approva (passa `wallet_address` quando il trasferimento non ne indica uno) e `confirmed: false` lo rifiuta. Didit risponde alla rete dopo la risposta, con gli stessi [nuovi tentativi](#consegna-e-nuovi-tentativi). Un trasferimento già risposto restituisce `409`.
* **Nessuna risposta successiva su `VERIFYVASP`.** VerifyVASP riceve la risposta nel momento in cui la chiede, quindi un trasferimento che richiederebbe la tua revisione viene rifiutato subito e non può essere deciso in seguito (`409`).

### Dati della controparte mascherati

Finché la titolarità del wallet non è confermata, i dati personali della controparte su un trasferimento in entrata vengono restituiti mascherati anziché omessi.
Viene mantenuta la prima lettera di ogni parola, mentre wallet, blockchain e instradamento VASP restano leggibili.
`data_masked` è `true`, e la controparte nel dettaglio della transazione, nell'elenco e nell'esportazione CSV viene mascherata allo stesso modo.

Una volta confermata la titolarità compaiono i valori reali e `data_unmasked` registra la voce di audit:

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

`reason` è `ownership_confirmed`, `wallet_proof`, `address_book_match`, `own_verified_wallet`, `inquiry_approved` (hai approvato una richiesta `TRP` o un messaggio `GTR` o `Sygna`), `known_payment_method` (il wallet dell'utente finale presente nei tuoi registri ha dato risposta) oppure `travel_address` (il Travel Address per wallet ha indicato il wallet).
Un trasferimento `INTERNAL` in entrata riporta `data_unmasked` con `reason: wallet_proof` fin dalla creazione, perché solo un destinatario che ha dimostrato il possesso del wallet ne riceve uno.
`actor` è l'email dell'utente della console o l'etichetta della chiave API, e resta vuoto per una decisione automatica.
Il report **Registro dei trasferimenti Travel Rule** (CSV e PDF) maschera i nomi di un trasferimento in entrata allo stesso modo finché la titolarità non è confermata. I report che invii a un'autorità di vigilanza, come il file XML goAML e il report normativo in PDF, riportano i dati reali della controparte.

### Riscontro sulle mancate corrispondenze

Un trasferimento `COUNTERPARTY_MISMATCHED_DATA` ora indica i campi che non corrispondono.
`data_match` contiene il confronto e `mismatched_fields` elenca i campi.
Entrambi riportano solo nomi di campi e risultati, mai valori, così restano leggibili mentre i dati sono mascherati:

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

La voce della cronologia indica i campi, ad esempio "la data di nascita del beneficiario non corrisponde al titolare del wallet".
Un rifiuto `TRP` dopo una mancata corrispondenza indica al VASP di origine quali campi differiscono, ad esempio "I dati del beneficiario non corrispondono al titolare del wallet: nome".
Ciò che apprende l'altro VASP è limitato di proposito: finché il nome è errato, il nome è l'unico campo segnalato (`mismatched_fields: ["name"]`, con ogni altro campo `not_compared`), e quando il nome corrisponde, viene indicato ogni campo che differisce. Questo vale per il lato mittente di uno scambio `INTERNAL` e per un rifiuto `TRP`.
Un nome mancante da entrambi i lati risulta `not_compared` e non è una mancata corrispondenza, e un paese corrisponde in base a ciò che indica, quindi `ES` e `ESP` coincidono.

#### Punteggio di corrispondenza del nome

Ogni trasferimento il cui nome è stato confrontato riporta `name_match`, e la voce della cronologia che lo ha deciso riporta lo stesso oggetto accanto al proprio `detail`:

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

* `score` è la somiglianza dei due nomi completi, da 0 a 100, e `0` se uno dei due è vuoto. `matched` è il risultato secondo `strictness`, quindi i due valori possono non coincidere: `FUZZY` decide in base al proprio rapporto di somiglianza di `0.85`.
* `matched_names` sono le parole del nome del trasferimento trovate nell'altro nome; `mismatched_names` sono le parole che un lato ha e l'altro no.
* `method` è `none`, `exact_token`, `token_subset`, `token_containment` o `sequence_ratio`, per `NONE`, `STRICT`, `DEFAULT`, `CONTAINS` e `FUZZY`.
* `compared_with` è `wallet_holder` (il titolare registrato per il wallet) oppure `counterparty_vasp` (il nome fornito dalla controparte nella pagina di risposta via email, o la risposta del Didit Test VASP).
* L'esito del trasferimento segue `data_match`, che confronta ogni campo, quindi un trasferimento può risultare `COUNTERPARTY_MISMATCHED_DATA` mentre `name_match.matched` è `true`.
* `name_match` è presente nell'oggetto trasferimento restituito dagli endpoint Travel Rule e nel campo `travel_rule` incorporato nella transazione, ed è `null` finché non è stato confrontato un nome. L'elenco dei trasferimenti e i webhook non lo riportano.
* I nomi restano nascosti finché le parti sono [mascherate](#dati-della-controparte-mascherati), e sulla copia dell'altro cliente di uno scambio `INTERNAL`.

### Messaggi e richieste di documenti

Due VASP possono risolvere un trasferimento contestato all'interno di Didit anziché via email.
`GET` e `POST /v3/transactions/{transaction_id}/travel-rule/messages/` elencano e inviano messaggi su un trasferimento:

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

* `kind` è `MESSAGE` (predefinito) o `DOCUMENT_REQUEST`. Una richiesta di documenti richiede almeno una voce in `requested_documents` (fino a 10); un messaggio richiede un `body` (fino a 5000 caratteri) o un file.
* `reply_to` indica un messaggio precedente dello stesso trasferimento. Una risposta dall'altro lato che contiene un documento soddisfa la richiesta di documenti a cui risponde, e su di essa viene impostato `fulfilled_at`. Una tua risposta non soddisfa mai una tua richiesta.
* Invia una richiesta multipart con `files` per allegare fino a 5 file da 10 MB ciascuno, in formato PDF, PNG, JPEG o WebP. Didit verifica il contenuto di ogni file, non solo il tipo dichiarato, e qualsiasi altro file restituisce `400` su `files` ("Attach PDF, PNG, JPEG or WebP files only.").
* Un trasferimento contiene fino a 100 messaggi, di cui fino a 20 possono avere allegati (ciascuno con fino a 5 file), contando entrambi i lati; oltre uno dei due limiti la richiesta riceve la risposta `400`. Gli allegati dei messaggi non contano tra i documenti propri della transazione.
* I messaggi funzionano sui canali `INTERNAL` ed `EMAIL`. Su `INTERNAL`, l'altro cliente Didit vede il messaggio dal proprio lato della coppia. Su `EMAIL`, alla controparte viene inviata un'email e risponde nel portale di ritiro. Se non è possibile inviare questa email di notifica, il messaggio viene comunque salvato e la richiesta riceve la risposta `201`.
* La richiesta riceve la risposta `409` con il motivo in `detail` per un trasferimento su `TRP`, `GTR`, `TRUST`, `VerifyVASP` o `Sygna` (questi protocolli non prevedono messaggi), un trasferimento senza ancora una controparte, un trasferimento `INTERNAL` i cui dati non corrispondevano al titolare del wallet (nulla è arrivato al destinatario), un trasferimento `INTERNAL` il cui destinatario non ha ancora dimostrato il controllo del wallet (da entrambi i lati, finché non lo fa), un trasferimento `EMAIL` la cui controparte non ha più un indirizzo email di compliance, e un trasferimento `EMAIL` il cui link di ritiro è scaduto o il cui trasferimento è chiuso.
* Nessun webhook viene inviato quando la controparte risponde. Leggi l'endpoint dei messaggi.
* L'email che informa la controparte di un nuovo messaggio viene inviata in inglese.

### Rubrica degli indirizzi wallet

Registra i wallet che controlli affinché i trasferimenti in entrata (canale `INTERNAL`, richieste `TRP` in entrata e [registrazioni successive al deposito](#registrazione-postuma-del-deposito-sunrise)) possano essere confrontati con essi, tramite `POST`/`GET /v3/travel-rule/wallet-addresses/` e `PATCH`/`DELETE /v3/travel-rule/wallet-addresses/{entry_uuid}/`.

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

| Campo | Tipo | Descrizione |
| - | - | - |
| `address` | stringa | L'indirizzo del wallet. Deve essere univoco per applicazione, `chain` e `memo` (l'indirizzo viene confrontato senza distinguere maiuscole e minuscole): un duplicato restituisce `400`. Un indirizzo X di XRP viene salvato come il suo indirizzo classico e il suo tag. Vuoto per una voce [importata tramite il suo hash](#importazione-di-wallet-in-blocco). |
| `address_hash` | stringa | Sola lettura. SHA-256 dell'indirizzo convertito in minuscolo, in esadecimale minuscolo. |
| `memo` | stringa | Facoltativo. Il destination tag o il memo che fa parte del wallet su una [rete con memo](#reti-con-memo-e-tag); vuoto per l'intero indirizzo. Alias: `destinationTag`. |
| `chain` | stringa | Identificatore facoltativo della chain, fino a 32 caratteri. Usa lo stesso token che riportano i tuoi trasferimenti (ad esempio `ETH` o `BTC`), oppure lascia il campo vuoto per abbinare i trasferimenti su qualsiasi chain - vedi la nota qui sotto. Un beneficiario Lightning (ID del nodo o Lightning Address) registrato su bitcoin viene salvato in minuscolo su `LIGHTNING`, dove vengono abbinati i trasferimenti [Lightning](#lightning). |
| `holder_name` | stringa | Nome del titolare del wallet, usato per il confronto del nome del beneficiario. |
| `holder_vendor_data` | stringa | Il tuo identificativo interno del titolare. |
| `entity_type` | stringa | Testo libero fino a 16 caratteri, predefinito `"individual"`. |
| `travel_address` | stringa | Facoltativo. Il Travel Address del VASP controparte per questo wallet, se lo conosci. Consente a Didit di instradare i trasferimenti verso questo beneficiario tramite il canale `TRP` anziché via email. |
| `receiving_travel_address` | stringa | Sola lettura. Il tuo Travel Address personale per questo wallet. Fornirlo a un VASP che invia a questo wallet: la sua richiesta TRP indicherà direttamente il wallet. Vuoto per un wallet registrato come appartenente a un altro VASP, mentre la Travel Rule è disattivata, e prima che il profilo del tuo VASP venga salvato. Smette di rispondere una volta eliminato il wallet. |
| `is_ownership_verified` | booleano | Sola lettura. Indica se l'assetto proprietario di questo indirizzo è stato dimostrato (tramite il [widget di verifica dell'assetto proprietario del wallet](https://docs.didit.me/it/transaction-monitoring/wallet-ownership-widget.md) o un'autodichiarazione). |
| `self_declared` | booleano | Solo scrittura, solo `POST`. Quando è `true`, la voce viene creata già verificata tramite una prova `SELF_DECLARATION`: i trasferimenti in entrata verso questo indirizzo saltano del tutto `UNCONFIRMED_OWNERSHIP` e vanno direttamente al confronto del nome. Restituisce `400` quando `allow_self_declaration` è disattivato nelle tue impostazioni. |

`PATCH` accetta `holder_name`, `holder_vendor_data`, `entity_type` e `travel_address`, e restituisce solo questi quattro campi.
`DELETE` elimina la voce (`204`): il suo indirizzo torna disponibile per una nuova registrazione e smette immediatamente di abbinarsi ai nuovi trasferimenti.

> [!NOTE]
>
> La corrispondenza non distingue maiuscole e minuscole sull'indirizzo, include il suo `memo` su una rete con memo e si applica per `chain`.
> Quando un trasferimento riporta una chain, una voce viene abbinata solo se il suo `chain` è lo stesso valore (senza distinguere maiuscole e minuscole) oppure è vuoto.
> I nomi delle chain vengono confrontati come testo, non tradotti: quindi una voce salvata come `ethereum` non viene abbinata a un trasferimento la cui chain è `ETH`.
> I trasferimenti in uscita prendono la chain da `beneficiary_data.chain`, poi da `transaction_details.crypto_params.crypto_chain`, poi da `custom_properties.crypto_chain`, poi dalla valuta (ad esempio `ETH`, oppure per `USDT` e `USDC` la chain dedotta da `payment_reference_id`), impostata solo quando è una chain riconosciuta da Didit, e le registrazioni post-deposito dal loro campo `chain`, in minuscolo.
> Le richieste `TRP` in entrata ignorano la chain: si abbinano per indirizzo oppure, quando la richiesta non indica alcun wallet, per nome del beneficiario tra le tue voci verificate.
> [`POST .../travel-rule/ownership/`](#conferma-dell’assetto-proprietario-del-wallet) abbina anche solo per indirizzo.
> Quando più voci corrispondono, il canale `INTERNAL` e le registrazioni post-deposito preferiscono una voce con assetto proprietario verificato, poi la più vecchia, mentre la ricerca `TRP` in uscita prende la voce più vecchia che memorizza un Travel Address.
> Le richieste `TRP` in entrata e l'endpoint dell'assetto proprietario accettano una qualsiasi delle voci corrispondenti, quindi mantieni una sola voce per indirizzo dove possibile.
> Il canale `INTERNAL` non abbina alcuna voce quando esistono voci verificate per l'indirizzo in più di un'altra applicazione.

#### Importazione di wallet in blocco

Importa fino a 10,000 wallet in una sola chiamata con [`POST /v3/travel-rule/wallet-addresses/import/`](https://docs.didit.me/it/management-api/travel-rule/import-wallet-addresses), in formato JSON (`{"entries": [...]}` oppure un semplice array) o come file CSV in UTF-8 di al massimo 5 MB con una riga di intestazione.
Una riga indica un wallet tramite il suo `address`, tramite `address_hash` (lo SHA-256 dell'indirizzo convertito in minuscolo, 64 caratteri esadecimali o 44 caratteri base64), o entrambi, più uno qualsiasi dei campi della voce descritti sopra.
Invia solo l'hash per registrare un wallet senza rivelarne l'indirizzo: abbina i trasferimenti verso quell'indirizzo come qualsiasi altra voce e può essere dimostrato con il [widget di verifica dell'assetto proprietario del wallet](https://docs.didit.me/it/transaction-monitoring/wallet-ownership-widget.md).

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

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

L'importazione è idempotente e riporta ogni riga nell'ordine in cui è stata inviata: `created`, `existing` (lo stesso wallet, chain e memo sono già presenti nel registro e non sono stati modificati), `duplicate` (ripete una riga precedente, indicata in `duplicate_of_row`) oppure `failed` con i relativi `errors`.
Una riga errata non fa fallire le altre: la risposta è `200` quando nessuna riga è fallita e `207` quando ne è fallita una, con i conteggi in `total`, `created`, `existing`, `duplicate` e `failed`.
Una cella CSV vuota viene considerata come non inviata, e le colonne che l'importazione non legge vengono ignorate, quindi un'esportazione da un altro strumento può essere importata così com'è.

Su `GET /v3/travel-rule/transfers/`, ogni riga riporta `originator_memo` e `beneficiary_memo` accanto ai due wallet.

### Invio via email alle controparti non raggiungibili

Quando nessun canale di protocollo può raggiungere la controparte, Didit ricorre a `EMAIL`: invia un link monouso per il ritiro a `beneficiary_data.counterparty_vasp_email` (oppure a un'email ricavata da `beneficiary_data.counterparty_vasp_name` tramite il registro della directory VASP).
Il destinatario non ha bisogno di un account Didit né di una chiave API: il token del link è l'autenticazione.
Ecco come viene inviata la richiesta:

* **Ai destinatari giusti.** Un `counterparty_vasp_email` che passi è l'unico destinatario. Altrimenti Didit scrive a un massimo di tre indirizzi: i [contatti](#contatti) della controparte che non hanno subito rimbalzi (prima i tuoi, poi i contatti della piattaforma, quelli che hanno risposto prima), poi l'email di conformità della voce della directory quando resta uno slot libero. Ogni indirizzo riceve una propria email.
* **A tuo nome.** L'email proviene dall'indirizzo di Didit come "*la tua ragione sociale* via Didit", nella lingua della giurisdizione della controparte (inglese quando non è nota), e il link apre la pagina di risposta in quella lingua. Non ricevi una copia: segui la cronologia del trasferimento.
* **Con i solleciti.** Finché la controparte non risponde, Didit la sollecita 72, 24 e 6 ore prima della scadenza, almeno 12 ore dopo la richiesta o l'ultimo sollecito, e mai dopo la scadenza.
* **Con la gestione dei rimbalzi.** Un rimbalzo o una segnalazione di spam contrassegna come non valido il contatto raggiunto, indicandone il motivo, e la cronologia del trasferimento lo registra. Un contatto della piattaforma diventa quindi non valido per ogni cliente Didit; il contatto della tua applicazione solo per la tua applicazione. Quando il servizio di invio email di Didit smette di inviare del tutto a un indirizzo (dopo un rimbalzo permanente, una segnalazione di spam o una cancellazione dell'iscrizione), ogni contatto a quell'indirizzo viene contrassegnato come non valido (`suppressed`), e tali contatti tornano validi quando l'invio a quell'indirizzo riprende. Quando non resta alcun indirizzo a cui scrivere, il trasferimento diventa `COUNTERPARTY_VASP_NOT_REACHABLE` con il motivo del server di posta ricevente nella sua cronologia. Un rimbalzo permanente o una segnalazione di spam sul `counterparty_vasp_email` che hai passato produce questo esito subito, perché è l'unico destinatario; un rimbalzo temporaneo (`soft_bounce`) su di esso, o sull'email di conformità della voce della directory, lascia la richiesta aperta per i solleciti.

Il link apre una pagina ospitata che mostra lo scambio in sospeso e richiama questi due endpoint pubblici per il destinatario.
Per il [trasferimento di esempio sopra](#invio-di-un-trasferimento), i dettagli del ritiro sono:

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

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

`reference` è lo `uuid` del trasferimento. `originator_data` e l'`ivms_request` IVMS 101 costruito a partire da esso contengono solo i campi dell'ordinante che condividi in [`data_sharing_fields`](#condivisione-dei-dati); il nome e il wallet sono sempre inclusi. `fiat_amount` e `fiat_currency` sono vuoti se non hai inviato un valore convertito, `contact` riporta il valore `?contact=` del link, e `decline_reasons` elenca i valori accettati da `decline_reason`. `join_invitation.eligible` è `true` finché la controparte ha un invito attivo a unirsi a Didit; il link di invito viaggia solo nell'email.

Questo endpoint restituisce l'importo memorizzato così com'è, quindi include tutte e 18 le cifre decimali invece della forma troncata usata nell'oggetto di dettaglio della transazione.

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

`decision` è `accept` oppure `decline`.
In caso di `accept`, il `beneficiary_name` fornito viene confrontato con `beneficiary_data.name` del trasferimento secondo la tua regola sul nome: `COMPLETED` in caso di corrispondenza, `COUNTERPARTY_MISMATCHED_DATA` altrimenti. La controparte può invece inviare una risposta IVMS 101 completa come `ivms_response`; in quel caso il nome del beneficiario da essa indicato prevale su `beneficiary_name`.
In caso di `decline`, il trasferimento passa a `COUNTERPARTY_VASP_GENERAL_DECLINE`. La controparte può indicare un `decline_reason` tra quelli in `decline_reasons`, con un `decline_detail` (fino a 512 caratteri, obbligatorio per `other`), e la cronologia del trasferimento lo registra, per esempio `counterparty declined: The beneficiary is not our customer`.
La risposta è il `{"status": "..."}` risultante, più `decline_reason` dopo un rifiuto. Una volta che la controparte ha risposto, entrambi gli endpoint restituiscono `410`.
Entrambi gli endpoint restituiscono `404` per un token sconosciuto e `410` quando la finestra si chiude, cioè quando il trasferimento è uscito da `AWAITING_COUNTERPARTY` oppure quando è trascorso il termine di conferma (`confirmation_timeout_hours` dopo la creazione o l'ultimo reinvio).

La controparte legge e risponde tramite il link di ritiro con `GET` e `POST /v3/travel-rule/pickup/{token}/messages/`.
Non richiede una chiave API, accetta solo allegati PDF, PNG, JPEG o WebP, e restituisce `410` quando il link scade o il trasferimento si chiude.
Un messaggio inviato da te mostra il nome del tuo VASP come `author` e come `uploaded_by` dell'allegato, mai la persona o la chiave API che lo ha inviato.

### Depositi non abbinati

Un deposito in entrata può arrivare prima che i dati Travel Rule del VASP di origine siano disponibili.
Tale deposito resta in `AWAITING_COUNTERPARTY` o `NOT_ENOUGH_COUNTERPARTY_DATA` finché i dati non arrivano.
Elenca i depositi che sono ancora in attesa con una chiave API che ha il privilegio transactions:

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

La risposta usa le stesse righe di `GET /v3/travel-rule/transfers/`, limitate ai depositi in entrata che attendono i dati del VASP di origine.

Quando i dati sono arrivati come messaggio ricevuto separato, abbinali tu stesso:

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

`{transaction_uuid}` è il deposito.
`transaction_id` è la transazione del messaggio Travel Rule ricevuto.
La chiamata restituisce `{ "deposit": ..., "message": ... }`.
Risponde `404` quando una delle due transazioni non esiste più, e `409` con `travel_rule_match_conflict` ("Questo deposito non può più essere abbinato.") quando una delle due parti è già passata oltre.

### Registrazione postuma del deposito (sunrise)

Quando un deposito in criptovalute viene regolato on-chain **prima** che avvenga qualsiasi scambio Travel Rule, perché il VASP mittente non era raggiungibile oppure stai recuperando depositi storici, registralo a posteriori con `POST /v3/travel-rule/inbound/`.

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

`originating_vasp.travel_address` deve essere un [Travel Address](#travel-address) reale e con checksum valido: un valore segnaposto restituisce `400` con `"Invalid travel address."`.
`originating_vasp.lei` deve essere vuoto oppure composto da 20 caratteri nel formato LEI (18 lettere o cifre, seguite da 2 cifre); qualsiasi altro valore restituisce `400` con `"Invalid LEI: expected 20 alphanumeric characters (ISO 17442)."`.
Didit verifica solo questo formato, non le cifre di controllo ISO 17442.

| Campo | Tipo | Descrizione |
| - | - | - |
| `chain` | stringa | Catena su cui è stato regolato il deposito, fino a 32 caratteri. Didit la converte in minuscolo e la usa per abbinarla alle voci della tua [rubrica degli indirizzi](#rubrica-degli-indirizzi-wallet), quindi usa lo stesso token delle tue voci (`eth` corrisponde a una voce memorizzata come `ETH`). Decide anche se il deposito può essere sottoposto a screening: `bitcoin`/`btc`, `ethereum`/`eth`, `solana`/`sol`, `tron`/`trx`, `polygon`/`matic`, `bsc`/`bnb`, `litecoin`/`ltc`, `ripple`/`xrp`, `bitcoin-cash`/`bch` e `dogecoin`/`doge`. |
| `txid` | stringa | L'hash della transazione on-chain. Serve a deduplicare: lo stesso `txid` + `wallet_address` restituisce il trasferimento esistente invece di crearne un duplicato. |
| `wallet_address` | stringa | Il wallet di destinazione su cui hai ricevuto il deposito. Un X-address XRP viene separato nel suo indirizzo classico e nel tag. |
| `memo` | stringa | Facoltativo. Il destination tag o memo del deposito su una [rete con memo](#reti-con-memo-e-tag): su un indirizzo di deposito condiviso indica il cliente a cui appartiene il deposito. |
| `amount` | stringa (decimale) | Importo del deposito. |
| `currency` | stringa | Asset del deposito. |
| `originator_data` | oggetto | Dati dell'ordinante forniti dal VASP mittente, se noti, come oggetto piatto: Didit legge `name` (oppure `full_name`), `first_name`, `last_name` e `vendor_data`. |
| `beneficiary_data` | oggetto | Dati del beneficiario (il tuo cliente), come oggetto piatto: Didit confronta il suo `name` con `holder_name` della voce della rubrica abbinata e vi aggiunge `wallet_address` e `chain`. |
| `utxo` | oggetto | Facoltativo, solo per le [catene UTXO](#trasferimenti-utxo). Gli `inputs` e gli `outputs` della transazione di deposito: il wallet del mittente è `originator_data.wallet_address` se lo dichiari, altrimenti l'input più grande. |
| `originating_vasp` | oggetto | `{ name, lei, travel_address }` facoltativo che descrive il mittente. `lei` deve rispettare il formato LEI indicato sopra e `travel_address` deve essere un Travel Address valido, altrimenti la richiesta restituisce `400`. Viene mantenuto su questo trasferimento come `metadata.originating_vasp`; non crea né modifica mai una voce della [directory](#come-le-voci-entrano-nella-directory) condivisa. |

Didit crea una transazione `travelRule` in entrata (oppure riutilizza un deposito in entrata già inviato con lo stesso hash e wallet, se non ha ancora alcun trasferimento Travel Rule) e risolve il trasferimento confrontando indirizzo e memo con la tua [rubrica degli indirizzi dei wallet](#rubrica-degli-indirizzi-wallet):

* Nessuna voce corrispondente -> `ON_HOLD`.
  Risolvilo con [`POST .../travel-rule/ownership/`](#conferma-dell’assetto-proprietario-del-wallet): `confirmed: true` aggiunge il wallet alla tua rubrica come verificato ed esegue il confronto del nome; in caso di corrispondenza il trasferimento passa a `COMPLETED`, poi a `FINISHED`.
* La voce esiste ma la proprietà non è dimostrata -> `UNCONFIRMED_OWNERSHIP`.
* Il nome del beneficiario non corrisponde al `holder_name` della voce -> `COUNTERPARTY_MISMATCHED_DATA`.
* Voce verificata e nome corrispondente -> `COMPLETED`, poi immediatamente `FINISHED` (il deposito è già stato regolato).

Con la voce verificata della rubrica registrata nell'[esempio sopra](#rubrica-degli-indirizzi-wallet), la risposta è:

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

L'`txn_id` della nuova transazione è `tr-in-`, seguito dai primi 80 caratteri del `txid` e da un hash di 12 caratteri calcolato su `txid` e wallet.
`created` è `true` (HTTP `201`) quando questa chiamata ha registrato il deposito, e `false` (HTTP `200`) quando lo stesso `txid` e lo stesso `wallet_address` erano già registrati; in quel caso il trasferimento esistente viene restituito invariato.
Nel percorso con voce verificata, entrambe le transizioni avvengono prima che l'endpoint risponda, quindi la risposta sincrona mostra già lo stato finale `FINISHED`; il passaggio intermedio `COMPLETED` resta comunque registrato nella `timeline` del trasferimento.
Ogni transizione genera un webhook `travel_rule.status.updated` (sia `COMPLETED` sia `FINISHED` ne generano uno).
Quando Didit ha creato una nuova transazione, invia prima [`transaction.created`](https://docs.didit.me/it/integration/webhooks#tipi-di-evento) e poi questi eventi.
La registrazione non comporta alcun costo per Travel Rule o monitoraggio.
Quando il monitoraggio crypto è attivo e il `chain` è uno di quelli che Didit può analizzare, anche un deposito appena creato viene sottoposto a screening e fatturato una sola volta alla tariffa Wallet Verification & Screening.

### Widget di verifica della proprietà del wallet

Per far uscire un trasferimento da `UNCONFIRMED_OWNERSHIP`, oppure per verificare in anticipo un wallet prima dell'arrivo di qualsiasi trasferimento, genera un widget ospitato per la verifica della proprietà del wallet con `POST /v3/travel-rule/widget-session/` e invia al tuo cliente l'`url` restituito. Il widget dimostra il controllo del wallet tramite firma di messaggi (inclusi gli account smart contract EVM, tramite ERC-1271 e ERC-6492), un test Satoshi, uno screenshot oppure un'autodichiarazione, quindi contrassegna come verificata la voce corrispondente nella rubrica, così lo scambio può proseguire.
Lo screenshot fa eccezione: da solo non verifica mai il wallet, quindi il tuo team di compliance lo esamina e conferma un trasferimento in `UNCONFIRMED_OWNERSHIP` con [`POST .../travel-rule/ownership/`](#conferma-dell’assetto-proprietario-del-wallet).

Per il flusso completo, i metodi di prova e l'avvertenza importante che il widget deve essere aperto in un browser reale, mai all'interno di una webview di un SDK mobile, consulta [Widget di verifica della proprietà del wallet](https://docs.didit.me/it/transaction-monitoring/wallet-ownership-widget.md).

## Directory

`GET /v3/travel-rule/vasps/` cerca nella directory dei VASP: le voci della directory condivisa più i membri della [rete Didit](#la-rete-didit). Ogni riga indica come la tua applicazione può raggiungere quel VASP oggi.

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

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

`search` corrisponde a un frammento del nome o di un alias, a un LEI esatto oppure a un dominio (`counterparty.example` o un URL su quel dominio). Restringi i risultati con:

| Parametro | Effetto |
| - | - |
| `network` | `GTR`, `TRUST`, `VERIFYVASP`, `SYGNA` o `TRISA`: solo le voci che la directory dei membri di quella rete elenca al momento. |
| `jurisdiction` | Codice paese ISO 3166 a due o tre lettere (alpha-2 o alpha-3). |
| `reachable` | `true`: solo i VASP a cui la tua applicazione ha un percorso disponibile. `false`: solo le voci che non può raggiungere oggi. |
| `kind` | `directory` per le voci condivise, `didit` per i membri della rete Didit. |
| `risk` | `LOW`, `MEDIUM` o `HIGH`: solo le voci della directory il cui `risk_level` appartiene a quella fascia. Vedi [Punteggio e livello di rischio](#punteggio-e-livello-di-rischio). |
| `responsiveness` | `RESPONSIVE`, `UNRESPONSIVE` o `UNKNOWN`: solo le voci della directory con quel `responsiveness.status`. Vedi [Reattività](#reattività). |

I membri della rete Didit non ricevono un punteggio, quindi `risk` e `responsiveness` restituiscono solo voci della directory. I risultati sono ordinati per nome e paginati con `limit` (predefinito `50`) e `offset`. Una rete, un codice paese, una fascia di rischio o uno stato di reattività sconosciuti restituiscono `400` con il nome del campo. `GET /v3/travel-rule/vasps/{vasp_id}/` restituisce una sola riga tramite il suo `id`. Il tuo profilo VASP non compare mai nei tuoi risultati.

`dd_status`, `dd_score`, `dd_score_breakdown`, `dd_assessed_at`, `dd_score_semantic`, `risk_level`, `responsiveness` e `essential_checks` contengono la valutazione di due diligence condivisa di una voce della directory. `decision`, `entity_screening` e `questionnaires` sono i registri che la tua applicazione tiene sul VASP, e nessun altro cliente li vede. Vedi [Due diligence sulle controparti](#due-diligence-sulla-controparte) per il significato di ciascuno, e basati su di essi tramite i [campi delle regole sulle controparti](#campi-delle-regole-e-preset) invece di creare rami condizionali in linea. I membri della rete Didit non ricevono un punteggio: `dd_status` è `COMPLETED`, `dd_score` è `null`, `risk_level` è vuoto e il dettaglio è vuoto.

### Route

`routes` elenca i modi in cui la tua applicazione può consegnare al VASP, nell'ordine in cui la scala di instradamento li prova, e `reachable` è `true` quando almeno una route è `available`:

* `TRP` quando la voce contiene un endpoint TRP verificato dalla directory.
* `GTR`, `TRUST`, `VERIFYVASP`, `SYGNA` quando una rete elenca il VASP con un codice. La route è `available` solo quando la tua applicazione può inviare tramite quella rete oggi (`via: own_membership` per la tua appartenenza collegata, `via: didit_membership` per quella di Didit). Altrimenti è `unavailable` con `reason: no_membership` o `reason: network_switched_off`, e non viene mai mostrata come un modo per raggiungere il VASP. Le adesioni di Didit alle reti non sono ancora attive, quindi oggi una route di rete è disponibile solo tramite un'adesione che hai collegato nel Marketplace.
* `EMAIL` quando la voce ha un contatto di compliance.
* `INTERNAL` per un membro della rete Didit.

Una voce `TRISA` compare in `networks` e ti indica chi è il VASP su TRISA, ma Didit non ha un canale TRISA, quindi non è mai una route.

Un'applicazione in sandbox invia solo al [Didit Test VASP](https://docs.didit.me/it/transaction-monitoring/travel-rule-sandbox.md), quindi nessuna route della directory è disponibile per essa: ogni route è `unavailable` con `reason: sandbox_application`, ogni riga ha `reachable: false`, e `reachable=true` non restituisce righe.

### Brand e relative entità

Un brand che opera tramite più entità regolamentate è una sola riga i cui `entities` sono le entità giuridiche che ricevono i suoi trasferimenti; una riga di entità punta al proprio brand tramite `umbrella`. Un trasferimento che indica il brand va a una delle sue entità, scelta tra tutte: quella nella giurisdizione indicata in `beneficiary_data.counterparty_vasp_jurisdiction`, altrimenti l'entità collegata all'indirizzo del wallet di destinazione dall'[attribuzione dell'analisi blockchain](#attribuzione-tramite-analisi-blockchain), altrimenti l'unica entità del brand quando non viene indicata alcuna giurisdizione. Solo a quel punto l'entità deve essere raggiungibile; se non lo è, il trasferimento non va mai a un'altra entità né al brand. Quando nessuna entità corrisponde (due corrispondono ugualmente, oppure la giurisdizione indicata non è quella di nessuna di esse), si usa la route propria del brand e, in sua assenza, il trasferimento è `COUNTERPARTY_VASP_NOT_FOUND`. La scelta di quale entità giuridica riceve i dati dell'originatore non è mai una supposizione e non viene mai decisa in base a quale entità ha un contatto.

Più voci con lo stesso nome, come società del gruppo che condividono una denominazione commerciale, si distinguono con la stessa regola: quella nella giurisdizione indicata, altrimenti quella collegata dall'attribuzione dell'analisi blockchain. Quando nessuna delle due ne sceglie una, non ne viene usata nessuna, e i dettagli contano come se non indicassero alcuna voce della directory.

### Contatti

`contacts` sono gli indirizzi a cui scrive la route `EMAIL`. I contatti con `scope: platform` servono ogni cliente Didit: Didit li cura (`source: staff`), oppure un indirizzo su un dominio proprio del VASP ha risposto a una richiesta tramite il suo link di risposta (`source: learned`). I contatti con `scope: application` sono riservati alla tua applicazione: quelli che aggiungi tu (`source: application`) e un indirizzo esterno ai domini propri del VASP che ha risposto a una tua richiesta (`source: learned`). Un trasferimento invia un'email prima al contatto della tua applicazione, poi a un contatto della piattaforma che ha già risposto in passato (con `verified_at` valorizzato), poi agli altri.

Gestisci i contatti della tua applicazione con l'API dei contatti delle controparti:

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

* `GET /v3/travel-rule/counterparty-contacts/` elenca ogni contatto a cui la tua applicazione può inviare, inclusi i contatti della piattaforma e quelli con consegna non riuscita, in ordine dal più recente, con paginazione tramite `limit` e `offset`. Filtra con `?counterparty=` e un `id` di voce della directory; un valore che non è un UUID restituisce `400`.
* `POST` aggiunge un contatto privato (`counterparty`, `email`, `name` facoltativo) e restituisce `201`. Aggiungere un indirizzo che la voce ha già tra i tuoi contatti restituisce quel contatto. Una voce sconosciuta restituisce `400` (`"No directory entry with this id."`).
* `DELETE /v3/travel-rule/counterparty-contacts/{contact_uuid}/` elimina uno dei tuoi contatti (`204`). I contatti della piattaforma non possono essere eliminati e restituiscono `404`.

Un contatto per il quale si è verificato un rimbalzo o che ha presentato un reclamo ha `is_invalid: true`, con `invalid_reason` (`hard_bounce`, `soft_bounce`, `spam_complaint` o `suppressed`), `invalid_detail` e `invalid_at`, e il canale `EMAIL` lo salta. `created_by` è vuoto nei contatti della piattaforma e in quelli aggiunti tramite una chiave API.

### Come le voci entrano nella directory

* Il registro interinale ESMA dei prestatori di servizi per le cripto-attività MiCA, letto ogni settimana: nome di ciascun prestatore, LEI e Stato membro di origine.
* La directory pubblica TRISA, letta ogni settimana: l'identità di ciascun membro, il suo paese e la sua voce TRISA. Una voce che la directory smette di mostrare per tre settimane viene rimossa.
* Il registro LEI globale completa il LEI, gli altri nomi legali e il paese di una voce, e trova il LEI di una voce tramite il suo nome legale esatto nel suo paese.
* [Attribuzione tramite analisi blockchain](#attribuzione-tramite-analisi-blockchain) aggiunge o associa il VASP che possiede un wallet di destinazione, e mantiene il nome attribuito come alias.
* Lo staff di Didit cura le voci: identificativi di instradamento e voci di rete che ha verificato, contatti per la compliance, alias, marchi e relative entità, duplicati uniti e voci nascoste.

I dati che un cliente segnala su una controparte, come un `originating_vasp` in entrata o un Travel Address, restano sul trasferimento di quel cliente e non modificano mai una voce condivisa. Le voci vengono associate prima per LEI, poi per nome esatto o alias, e vengono arricchite anziché duplicate.

### La rete Didit

Il tuo profilo VASP è un membro della rete Didit, quindi altri clienti Didit lo trovano nella directory e nel selettore VASP dell'utente finale, solo quando tutte queste condizioni sono soddisfatte:

* la tua applicazione è in produzione (non sandbox) e Travel Rule è attiva;
* `is_discoverable` è `true` e `legal_name` è impostato;
* `compliance_email` è impostato e confermato: invia la conferma con `POST /v3/travel-rule/settings/compliance-email/confirmation/` e apri il link ricevuto via email. Cambiare l'indirizzo richiede una nuova conferma;
* Didit non ha contrassegnato l'applicazione come di test, demo o interna.

Il canale `INTERNAL` invia a un wallet che hai dimostrato di possedere, come descritto in [Invio di un trasferimento](#invio-di-un-trasferimento): richiede che la tua applicazione sia in produzione, Travel Rule attiva e `is_discoverable`, non il resto dell'elenco.

`GET /v3/travel-rule/settings/` restituisce `didit_network`: `listed`, `compliance_email_confirmed`, e in `missing` ciascuna condizione ancora non soddisfatta (`travel_rule_off`, `sandbox_application`, `not_discoverable`, `legal_name_missing`, `compliance_email_missing`, `compliance_email_unconfirmed`, `excluded_by_staff`, `internal_organization`).

### Identificativi di instradamento

L'instradamento in uscita consulta una voce della directory ogni volta che il tuo trasferimento indica la controparte tramite `counterparty_vasp_lei` o `counterparty_vasp_name` (funziona anche un alias). Una voce contiene un identificativo per ciascuna rete su cui può essere raggiunta, un endpoint TRP verificato e i suoi contatti per la compliance, e `routes` mostra quali di essi la tua applicazione può usare. Puoi sempre aggirare la directory su un singolo trasferimento passando i campi espliciti descritti in [Campi di risoluzione della controparte](#campi-di-risoluzione-della-controparte).

## Due diligence sulla controparte

Prima che i fondi dei tuoi clienti raggiungano un altro VASP, devi sapere chi è quel VASP e se lo accetti. La due diligence su una controparte ha due livelli:

* **La valutazione condivisa.** Ogni voce della directory riporta un punteggio di due diligence, il suo livello di rischio, uno stato di reattività e un report sui controlli essenziali. Didit li calcola dai dati della piattaforma, quindi ogni cliente vede gli stessi valori.
* **I tuoi registri.** La tua decisione sul VASP, il tuo screening di sanzioni e notizie negative su di esso e i questionari di due diligence scambiati con esso appartengono solo alla tua applicazione. Nessun altro cliente li vede e non modificano mai la voce condivisa.

I tuoi registri funzionano allo stesso modo per una voce della directory e per un membro della [rete Didit](#la-rete-didit): gestiscili usando l'`id` mostrato dalla [directory](#directory).

| Endpoint | Cosa fa |
| - | - |
| `GET` / `PUT` / `DELETE /v3/travel-rule/vasps/{vasp_id}/decision/` | Legge, imposta o cancella [la tua decisione](#la-tua-decisione-su-una-controparte) sulla controparte. |
| `GET` / `POST /v3/travel-rule/vasps/{vasp_id}/screening/` | Legge il tuo ultimo [screening della controparte](#screening-della-controparte), oppure ne avvia uno. |
| `GET` / `POST /v3/travel-rule/vasps/{vasp_id}/questionnaires/` | Elenca i tuoi [questionari di due diligence](#questionario-di-due-diligence) con la controparte, oppure ne invia uno. |
| `GET /v3/travel-rule/transfers/?counterparty={vasp_id}` | I tuoi [trasferimenti con quella controparte](#trasferimenti-con-una-controparte). |

### Punteggio e livello di rischio

`dd_score` va da 0 a 100 e **un valore più alto significa più sicurezza**. Ogni risultato lo dichiara in `dd_score_semantic`, che vale sempre `higher_is_safer`. `risk_level` è la fascia in cui ricade il punteggio:

| `risk_level` | `dd_score` |
| - | - |
| `LOW` | 70 o più |
| `MEDIUM` | Da 40 a 69 |
| `HIGH` | Sotto 40 |

Il punteggio è la somma di sette componenti. `dd_score_breakdown` mostra ciascuna come `{points, max, reason, detail}`: `max` è il peso della componente, `reason` un codice leggibile dalla macchina che puoi tradurre, e `detail` una spiegazione in inglese su una riga.

| Componente | Peso | Come assegna il punteggio | Codici `reason` |
| - | - | - | - |
| `jurisdiction` | 25 | Punteggio pieno quando il paese della voce non è nella lista predefinita delle giurisdizioni ad alto rischio (`IRN`, `PRK`, `SYR`, `AFG`, `RUS`, `MMR`), nessun punto quando lo è, metà punteggio quando il paese è sconosciuto. | `jurisdiction_not_high_risk`, `jurisdiction_high_risk`, `jurisdiction_unknown` |
| `verification` | 15 | Lo stato di verifica di Didit della voce (`dd_status`): punteggio pieno per `COMPLETED`, metà per `IN_PROGRESS`, un quarto per `NOT_STARTED`, nessun punto per `REJECTED`. | `dd_status_completed`, `dd_status_in_progress`, `dd_status_not_started`, `dd_status_rejected` |
| `protocol` | 15 | Punteggio pieno quando un canale di protocollo nativo raggiunge la voce (un endpoint TRP o il canale `INTERNAL`), 40 per cento quando vi arriva solo il fallback via email, nessun punto senza un canale raggiungibile. | `native_rail`, `email_only`, `no_rail` |
| `lei` | 10 | Punteggio pieno con un LEI valido registrato, nessun punto senza. | `lei_valid`, `lei_missing` |
| `history` | 10 | La quota degli scambi della voce con esito definito che sono riusciti, metà punteggio senza alcuno scambio. | `history`, `no_history` |
| `essentials` | 15 | La quota dei [controlli essenziali](#controlli-essenziali) definiti che risultano superati, metà punteggio finché nessuno ha un esito definito. | `essential_checks`, `no_essential_checks` |
| `responsiveness` | 10 | Punteggio pieno per `RESPONSIVE`, nessun punto per `UNRESPONSIVE`, metà per `UNKNOWN`. Vedi [Reattività](#reattività). | `responsive`, `unresponsive`, `responsiveness_unknown` |

I punti sono arrotondati a una cifra decimale e il totale a un numero intero. `history` considera le stesse richieste della [reattività](#reattività), senza finestra temporale: uno scambio `COMPLETED` o `FINISHED` è un successo, mentre `EXPIRED`, `COUNTERPARTY_MISMATCHED_DATA` o `COUNTERPARTY_VASP_GENERAL_DECLINE` sono un insuccesso. Un annullamento è un atto del mittente e non conta mai.

Didit ricalcola la valutazione quando uno scambio con la voce viene completato, terminato, scaduto, reso non corrispondente o rifiutato, quando la voce viene aggiornata o curata, e per ogni voce durante l'aggiornamento settimanale della directory. `dd_assessed_at` indica quando è stata eseguita l'ultima volta; una voce non ancora valutata non ha `dd_assessed_at`, ha `dd_score` pari a `0` e `risk_level` vuoto, quindi leggi `risk_level` invece del punteggio grezzo. I membri della rete Didit non vengono valutati: il loro `dd_score` è `null`, il loro `risk_level` è vuoto e il loro `dd_score_breakdown` è vuoto.

### Controlli essenziali

`essential_checks` è un breve report su quattro controlli che Didit esegue su ogni voce della directory, usando solo le fonti verificate della piattaforma, mai dati segnalati da un cliente:

| `id` del controllo | Superato quando |
| - | - |
| `registration` | Un registro ufficiale elenca il VASP: il registro provvisorio MiCA dell'UE dei fornitori di servizi per le cripto-attività, la directory pubblica TRISA, oppure il registro globale dei LEI con un LEI emesso. |
| `licence` | Il registro MiCA riporta per il VASP un'autorizzazione non ancora cessata. |
| `domain` | Il dominio della voce corrisponde al suo endpoint TRP o al sito web indicato dal suo registro. |
| `lei` | La registrazione LEI della voce è attiva ed emessa, e la sua ragione sociale e il suo paese corrispondono alla voce. |

Ogni controllo in `checks` riporta il proprio `status` (`pass`, `fail`, oppure `unknown` quando nessuna fonte disponibile consente di determinarlo), un `reason` leggibile dalla macchina e un `detail` in inglese su una riga. `passed`, `failed`, `unknown` e `total` li contano, `level` vale `essential` e `checked_at` indica quando è stato generato il report. La componente `essentials` assegna il punteggio in base alla quota dei controlli definiti che risultano superati, quindi un controllo `unknown` non conta né a favore né contro la voce. Il report è vuoto finché il primo aggiornamento settimanale della directory non controlla una voce, ed è sempre vuoto per un membro della rete Didit.

### Reattività

`responsiveness` indica se il VASP risponde alle richieste della Travel Rule:

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

`total` conta le richieste che i clienti Didit hanno avviato verso il VASP negli ultimi 90 giorni e il cui esito è definito, mentre `answered` conta quelle a cui ha risposto:

* **Conteggiate:** le richieste inviate tramite un canale di rete o di protocollo, e le richieste inviate via email a un indirizzo condiviso, cioè l'indirizzo di compliance della voce o un contatto della piattaforma.
* **Mai conteggiate:** una richiesta inviata via email a un indirizzo digitato da un cliente, o a un contatto privato di un cliente. Quello scambio resta nello storico trasferimenti del cliente e non etichetta mai il VASP per tutti gli altri.
* **Con risposta:** `COMPLETED`, `FINISHED`, `COUNTERPARTY_VASP_GENERAL_DECLINE` oppure `COUNTERPARTY_MISMATCHED_DATA`. Un rifiuto o una mancata corrispondenza è una risposta: il VASP ha interagito.
* **Senza risposta:** `EXPIRED`.
* **Non conteggiate in nessuno dei due casi:** ogni altro stato. Una richiesta `CANCELLED` è un atto del mittente, `COUNTERPARTY_VASP_NOT_REACHABLE` può essere un problema dal lato del mittente, e una richiesta ancora in corso non ha un esito definito.

| `status` | Quando |
| - | - |
| `UNKNOWN` | Meno di 5 richieste su cui è stata presa una decisione nella finestra, quindi una singola richiesta scaduta non etichetta mai un VASP. |
| `UNRESPONSIVE` | Il VASP ha risposto a meno del 10 per cento delle sue richieste su cui è stata presa una decisione. |
| `RESPONSIVE` | Negli altri casi. |

I membri della rete Didit rispondono all'interno di Didit e mostrano sempre `UNKNOWN` con conteggi pari a zero. Agisci su una controparte non reattiva con la [politica di non risposta](#politiche-sunrise-e-per-le-controparti-non-responsive) oppure con il [preset](#campi-delle-regole-e-preset) `travel-rule-counterparty-unresponsive`.

### La tua decisione su una controparte

Registra il verdetto del tuo team di compliance su una controparte con `PUT /v3/travel-rule/vasps/{vasp_id}/decision/`:

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

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

| `decision` | Significato | Preset che agisce su di essa |
| - | - | - |
| `APPROVED` | Il tuo team ha approvato la controparte. | Nessuno |
| `RESTRICTED` | I trasferimenti verso di essa possono procedere dopo una revisione. | `travel-rule-counterparty-restricted` li trattiene per la revisione. |
| `BLOCKED` | Il tuo team ha rifiutato la controparte. | `travel-rule-counterparty-blocked` li rifiuta. |

* La decisione è privata per la tua applicazione: un altro cliente non la vede mai, e non modifica mai la voce condivisa.
* Una decisione da sola non cambia nulla e non cambia mai l'instradamento di un trasferimento. Raggiunge le tue transazioni tramite il [campo di regola](#campi-delle-regole-e-preset) `counterparty_dd_status`: installa i preset oppure scrivi una tua regola su di esso.
* Una decisione su un marchio copre ciascuna delle sue [entità](#brand-e-relative-entità) che non ha una decisione propria, e l'entità mostra il marchio in `inherited_from`. Una decisione sull'entità sostituisce quella del marchio per quell'entità.
* `GET` restituisce la decisione applicabile, oppure `{"decision": null}`. `DELETE` cancella la tua decisione e restituisce quella che si applica dopo: la decisione del marchio per un'entità, altrimenti `null`. Risponde `404` quando la tua applicazione non ha una decisione propria sulla controparte.
* `reason` è facoltativo, fino a 255 caratteri, e ogni `PUT` lo sostituisce. `decided_by` è l'utente della console che ha preso o modificato per ultimo la decisione, ed è vuoto quando l'ha fatto una chiave API.

### Screening della controparte

Lo screening della controparte verifica il VASP della controparte in quanto azienda, rispetto a sanzioni e notizie negative. Richiede l'attivazione e comporta un costo: attivalo con `counterparty_screening_enabled` nelle tue [impostazioni](#configurazione). Finché è disattivato, non viene eseguito alcuno screening né addebitato alcun costo.

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

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

* **Fatturazione.** Ogni nuovo screening costa il [prezzo](https://docs.didit.me/it/getting-started/pricing.md) Screening AML aziendale della tua organizzazione. `GET /v3/travel-rule/vasps/{vasp_id}/screening/` restituisce questo `price`, `fresh_days` e se lo screening è `enabled`, senza alcun costo. Uno screening di meno di 30 giorni è recente: `POST` lo restituisce di nuovo con `200` e `outcome: reused` senza addebitare nulla, a meno che tu non invii `refresh: true`. Un nuovo screening restituisce `201` con `outcome: screened`. Le applicazioni sandbox non vengono mai sottoposte a screening né addebitate.
* **Screening automatico.** Con lo screening attivo, Didit sottopone a screening anche la controparte raggiunta da uno scambio in uscita quando lo scambio inizia, prima che le tue regole valutino la transazione, con lo stesso riutilizzo e la stessa fatturazione. Un rifiuto o un errore in questa fase non fa mai fallire il trasferimento.
* **Esito.** `status` è `Approved` quando non c'è alcuna possibile corrispondenza che richieda attenzione, e `In Review` o `Declined` per una possibile corrispondenza con sanzioni o notizie negative. `flagged` è `true` mentre uno screening recente è `In Review` o `Declined`.
* **Effetto.** Finché il tuo ultimo screening di una controparte è segnalato e lo screening resta attivo, `counterparty_risk_level` vale `HIGH` nelle tue regole, quindi il preset `travel-rule-counterparty-high-risk`, una volta installato, trattiene i suoi trasferimenti. Il `risk_level` condiviso nella directory non cambia.
* **Privacy.** Lo screening è privato per la tua applicazione: un altro cliente non lo vede mai, e non modifica mai la voce condivisa. La directory mostra il tuo ultimo screening come `entity_screening`.
* **Rifiuti.** `409` quando lo screening è disattivato, per un'applicazione sandbox, o mentre è già in corso uno screening della stessa controparte. `403` con `code: insufficient_credits` quando il tuo saldo non copre il prezzo. `502` quando lo screening non può essere completato. In nessuno di questi casi viene addebitato alcunché.

### Questionario di due diligence

Chiedi alla controparte le risposte di due diligence con il questionario standard di Didit. `POST /v3/travel-rule/vasps/{vasp_id}/questionnaires/` lo invia via email a un indirizzo di compliance registrato per la controparte, con un link monouso a una pagina di risposta:

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

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

* **Dove viene inviato.** `sent_to` deve essere un indirizzo di compliance registrato: per una voce della directory, il suo indirizzo di compliance o un contatto che la tua applicazione vede in `contacts`; per un membro della rete Didit, la sua email di compliance confermata. Omettilo per usare l'indirizzo a cui va un'email Travel Rule alla controparte: prima il tuo contatto, poi un contatto della piattaforma, poi l'indirizzo di compliance della voce. Didit non invia mai il questionario a nessun altro destinatario, e restituisce `400` quando la controparte non ha un indirizzo di compliance registrato.
* **Risposta.** Il link apre `/v3/travel-rule/questionnaires/{token}/`, una pagina per una persona della controparte che non richiede account né chiave API. Risponde a ogni domanda, fino a 2.000 caratteri ciascuna (`N/A` dove una domanda non si applica), e invia una sola volta. Una controparte può anche inviare `{"answers": {"<question id>": "<answer>"}}` allo stesso link. Un link già usato, sostituito o oltre la scadenza mostra invece una pagina di scadenza. L'email e la pagina sono tradotte; le domande stesse restano sempre in inglese, così il loro significato non cambia tra le lingue.
* **Scadenze.** La controparte ha 30 giorni per rispondere (`expires_at`). Le risposte restano valide per 365 giorni (`valid_until`), e `current` è `true` fino ad allora. Un questionario senza risposta oltre la scadenza, e le risposte oltre la loro validità, diventano `EXPIRED`.
* **Un questionario aperto per controparte.** Un nuovo invio sostituisce il tuo precedente questionario senza risposta verso la stessa controparte: diventa `EXPIRED` e il suo link smette di funzionare. A un indirizzo può essere inviata una sola email al minuto; un invio più rapido restituisce `429`.
* **Lettura delle risposte.** `GET /v3/travel-rule/vasps/{vasp_id}/questionnaires/` elenca i tuoi questionari con la controparte, dal più recente, con `answers` indicizzate per l'ID della domanda una volta ricevute le risposte. La directory li mostra come `questionnaires`. Sono privati per la tua applicazione.

La versione `1` del modulo pone queste dodici domande:

| ID domanda | Domanda |
| - | - |
| `legal_name` | Ragione sociale dell'entità e giurisdizione di costituzione. |
| `licensing` | Licenze o registrazioni detenute per i servizi di asset virtuali: autorità di vigilanza, numero di licenza e stato in ciascuna giurisdizione. |
| `jurisdictions` | Giurisdizioni in cui operi, e quelle in cui sei escluso o soggetto a restrizioni. |
| `aml_program` | Sintesi del tuo programma AML/CFT: politiche, procedure e data dell'ultimo audit o revisione indipendente. |
| `compliance_officer` | Nome e ruolo del tuo responsabile della compliance e modalità per contattarlo. |
| `sanctions_screening` | Come effettui lo screening di clienti e controparti rispetto a sanzioni e notizie negative: fornitore o liste, frequenza ed escalation. |
| `transaction_monitoring` | Come monitori le transazioni per individuare attività sospette: strumenti, soglie e prassi di segnalazione. |
| `travel_rule` | Come rispetti la Travel Rule: protocolli e reti utilizzati, e il tuo tempo di risposta tipico a una richiesta. |
| `custody` | Modalità di custodia degli asset dei clienti: custode qualificato, assicurazione e segregazione. |
| `ownership` | Titolari effettivi con una quota pari o superiore al 25 percento, e qualsiasi entità madre o ombrello. |
| `record_keeping` | Prassi di conservazione delle registrazioni e periodo di conservazione per i dati della Travel Rule e delle transazioni. |
| `data_protection` | Come proteggi i dati personali condivisi a fini di compliance e dove vengono archiviati. |

### Trasferimenti con una controparte

[`GET /v3/travel-rule/transfers/?counterparty={vasp_id}`](https://docs.didit.me/it/management-api/travel-rule/list-transfers) elenca i trasferimenti Travel Rule della tua applicazione con una controparte, dal più recente al più vecchio, in base all'`id` mostrato dalla directory: i tuoi trasferimenti la cui controparte è quella voce della directory, oppure i tuoi scambi `INTERNAL` con quel membro della rete Didit. Un valore che non è un id valido restituisce `400`.
Ogni riga riporta `reason` subito dopo `status`: la [`reason`](#perché-un-trasferimento-è-bloccato) del trasferimento stesso, così l'elenco ti permette di distinguere il mancato recapito dell'email di compliance dall'assenza di un percorso per la controparte, senza aprire ogni trasferimento.

### Politiche sunrise e per le controparti non responsive

Quando un trasferimento scade (è trascorso `confirmation_timeout_hours` mentre era `AWAITING_COUNTERPARTY`), `timeout_outcome` decide cosa accade alla sua transazione. Due impostazioni ti permettono di trattare in modo diverso due motivi comuni di timeout:

| Impostazione | Si applica quando la controparte è una voce della directory che |
| - | - |
| `sunrise_policy` | Si trova in una giurisdizione elencata in `sunrise_jurisdictions`: un paese che non applica ancora la Travel Rule, quindi il VASP non è obbligato a rispondere. |
| `non_responsive_policy` | Ha `responsiveness.status` `UNRESPONSIVE`. |

Entrambe accettano `HOLD`, `REJECT` o `PROCEED`, con lo stesso significato di `timeout_outcome`, oppure una stringa vuota per seguire `timeout_outcome`. Entrambe sono vuote per impostazione predefinita, quindi nulla cambia finché non ne imposti una:

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

La prima di queste che si applica determina l'esito:

1. `sunrise_policy`, quando è impostata e la giurisdizione della controparte è in `sunrise_jurisdictions`.
2. `non_responsive_policy`, quando è impostata e la controparte è `UNRESPONSIVE`.
3. `timeout_outcome` in ogni altro caso, incluso un trasferimento verso un membro della rete Didit o verso una controparte senza voce nella directory.

`sunrise_jurisdictions` è di sola lettura e attualmente è `["CO", "KH", "VN"]`. Solo questi paesi vengono considerati in un periodo sunrise: qualsiasi altra giurisdizione, e una giurisdizione vuota o sconosciuta, segue `timeout_outcome`, così una controparte non riceve mai la tua politica sunrise per errore. La cronologia del trasferimento scaduto indica l'esito applicato, per esempio `sunrise_policy=PROCEED (counterparty jurisdiction CO does not enforce the Travel Rule yet)`. Le tue regole continuano a essere eseguite dopo la scadenza, quindi una regola come `tr_eu_expired_review` del TFR UE può ancora spostare la transazione in revisione con `PROCEED`.

### Campi delle regole e preset

Quattro campi della [regola](https://docs.didit.me/it/transaction-monitoring/rules.md) contengono ciò che la tua applicazione sa sulla controparte raggiunta dallo scambio Travel Rule di una transazione: la sua voce nella directory o, per uno scambio `INTERNAL`, il cliente Didit che lo ha ricevuto. Ogni campo è vuoto quando lo scambio non ha raggiunto alcuna controparte nota.

| Campo | Valore |
| - | - |
| `counterparty_dd_status` | La tua [decisione](#la-tua-decisione-su-una-controparte): `APPROVED`, `RESTRICTED` o `BLOCKED`, oppure lo stato di un'entità che segue quello del proprio brand. Vuoto quando non ne hai presa alcuna. Mai la decisione di un altro cliente. |
| `counterparty_risk_level` | Il `risk_level` della voce (`LOW`, `MEDIUM` o `HIGH`), oppure `HIGH` mentre il tuo [screening](#screening-della-controparte) della controparte è segnalato. Vuoto per una voce non ancora valutata e per un membro della rete Didit, a meno che il tuo screening di quel membro non sia contrassegnato. |
| `counterparty_jurisdiction` | Il paese della controparte, dalla voce della directory o dal profilo del membro della rete Didit. I codici ISO-2 e ISO-3 vengono confrontati entrambi, come gli altri campi paese. |
| `counterparty_responsiveness` | Il `responsiveness.status` della voce: `RESPONSIVE`, `UNRESPONSIVE` o `UNKNOWN`. Vuoto per un membro della rete Didit. |

Cinque preset del bundle `travel_rule` agiscono su questi campi. Installali da **Transactions → Rules → Library** nella Business Console oppure con la [API della libreria di regole](https://docs.didit.me/it/management-api/transactions/rules-install.md):

| `library_key` | Trigger | Azione predefinita |
| - | - | - |
| `travel-rule-counterparty-blocked` | `counterparty_dd_status` è `BLOCKED` | +90 al punteggio, `DECLINED` |
| `travel-rule-counterparty-restricted` | `counterparty_dd_status` è `RESTRICTED` | +50 al punteggio, `IN_REVIEW` |
| `travel-rule-counterparty-high-risk` | `counterparty_risk_level` è `HIGH` | +40 al punteggio, `IN_REVIEW` |
| `travel-rule-counterparty-high-risk-jurisdiction` | `counterparty_jurisdiction` è nella lista predefinita dei paesi ad alto rischio (`IRN`, `PRK`, `SYR`, `AFG`, `RUS`, `MMR`) | +60 al punteggio, `IN_REVIEW` |
| `travel-rule-counterparty-unresponsive` | `counterparty_responsiveness` è `UNRESPONSIVE` | +30 al punteggio, `IN_REVIEW` |

Tutti e cinque si applicano solo alle transazioni Travel Rule.

## Webhook

Iscrivi una destinazione a `travel_rule.status.updated` per ricevere una notifica a ogni transizione di stato di ogni trasferimento nella tua applicazione, in uscita e in entrata, incluse le tratte sul rail `INTERNAL`.
Il routing viene eseguito dopo che la creazione della transazione restituisce una risposta, quindi esiti come `COUNTERPARTY_VASP_NOT_FOUND`, `COUNTERPARTY_VASP_NOT_REACHABLE` o uno scambio `INTERNAL` che si chiude subito ti arrivano tramite questo evento e non nella risposta della creazione.

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

`rail` resta vuoto finché non viene selezionato un rail.
Per una stessa transazione, Didit invia `travel_rule.status.updated` dopo `transaction.created`: quando Didit crea la transazione (con la tua `POST /v3/transactions/`, una registrazione sunrise, un'interrogazione `TRP` in entrata o la tratta in entrata sul rail `INTERNAL`), invia prima `transaction.created`.
Ogni evento viene consegnato e ritentato in modo indipendente, quindi un `transaction.created` che ha richiesto un nuovo tentativo può arrivare dopo un evento di stato. Usa `transaction_id` come chiave del tuo handler e leggi la transazione quando un evento di stato ne indica una che non hai ancora visto.
Un trasferimento inviato tramite `TRUST` non riceve l'evento `COMPLETED`: TRUST non restituisce nulla che Didit possa leggere, quindi, a meno che l'invio non fallisca o tu non lo annulli, il suo ultimo evento è `EXPIRED`. Tramite `GTR`, `VERIFYVASP` e `SYGNA`, l'evento segue la risposta che Didit legge dalla rete.
Anche le applicazioni sandbox inviano questo evento, con `"environment": "sandbox"`. Un trasferimento a cui ha risposto il [Didit Test VASP](https://docs.didit.me/it/transaction-monitoring/travel-rule-sandbox.md) riporta `rail: "TEST_VASP"`, `test_vasp: true` e `test_vasp_scenario`.

Consulta la [guida ai webhook](https://docs.didit.me/it/integration/webhooks.md#tipi-di-evento) per il catalogo completo degli eventi, la verifica della firma e la politica di nuovo tentativo.

## Prezzi

La commissione Travel Rule è di **\$0.02 per ogni scambio in uscita avviato**, addebitata una sola volta alla creazione della transazione, indipendentemente da quante transizioni di stato lo scambio attraversi in seguito. Un `resend` non la addebita mai di nuovo.

* Si applica a una transazione `travelRule` in uscita su un'applicazione con Travel Rule attiva, il cui importo è pari o superiore alla tua `threshold_amount`, quindi Didit avvia per essa uno scambio gestito. Vi rientra anche un trasferimento verso un wallet in autocustodia o verso il wallet verificato del tuo utente: in quel caso la prova di proprietà è il suo scambio.
* Ogni altra transazione in uscita che contiene dati Travel Rule viene fatturata come Transaction Screening standard, che il tuo piano include fino alla propria [quota mensile di transazioni](https://docs.didit.me/it/getting-started/pricing.md#monitoraggio-delle-transazioni-kyt) e che viene prezzato \$0.001 oltre tale soglia: un trasferimento sotto la tua soglia, un pagamento Lightning a cui la Travel Rule non si applica e un trasferimento registrato in modo passivo mentre Travel Rule è disattivata. Una transazione viene fatturata su una sola delle due voci, mai su entrambe.
* Le transazioni `travelRule` in entrata non comportano commissioni Travel Rule o di monitoraggio: la tratta in entrata che Didit crea sull'applicazione del beneficiario tramite il rail `INTERNAL`, le interrogazioni `TRP` in entrata e le [registrazioni successive al deposito](#registrazione-postuma-del-deposito-sunrise).
* Un'applicazione che ha aderito a Travel Rule gratuitamente non paga nessuna delle due commissioni sulle transazioni `travelRule` in uscita finché non attiva la fatturazione in uscita con `POST /v3/travel-rule/workspace/billing/`; la ricezione resta gratuita.
* Le applicazioni sandbox non vengono mai addebitate.
* La commissione Travel Rule è di $0.02 e Transaction Screening costa $0.001 oltre la tua quota. Ogni transazione viene addebitata al prezzo della voce applicabile.
* Se sulla stessa transazione viene eseguito anche lo screening AML crittografico o dei wallet (per esempio un deposito in entrata con `currency_kind: "crypto"` e monitoraggio attivo), questo viene fatturato a parte alla tariffa standard di Wallet Verification & Screening e non è incluso nella commissione Travel Rule.
* Lo [screening della controparte](#screening-della-controparte) è facoltativo e viene fatturato a parte, al prezzo dello Screening AML per aziende per ogni screening; uno screening di età inferiore a 30 giorni viene riutilizzato senza costi. Decisioni, questionari e la valutazione di due diligence della directory non hanno alcun costo.

### Prezzi dell'attribuzione

[L'attribuzione tramite analisi blockchain](#attribuzione-tramite-analisi-blockchain) richiede una ricerca del wallet presso il fornitore di analisi, e ottieni sempre il valore completo di quella ricerca:

* **Il monitoraggio crypto ha già sottoposto a screening il wallet su questa transazione**: il risultato memorizzato viene riutilizzato. Una chiamata all'analisi, un addebito di Wallet Verification & Screening (quello già effettuato dal monitoraggio crypto). L'attribuzione non aggiunge nulla.
* **Il monitoraggio crypto non è stato eseguito**: Didit effettua una sola volta la chiamata necessaria all'analisi e ne trasferisce l'intero valore: la transazione viene addebitata alla tariffa standard di Wallet Verification & Screening (\$0.15 con analisi gestita da Didit) e riceve in cambio l'output completo dello screening crypto, cioè punteggio di rischio, categoria di rischio del wallet e snapshot della rete, non solo il nome del VASP. La voce di utilizzo è contrassegnata con il trigger `travel_rule_attribution`, così l'addebito è spiegabile.
* **Chiave di analisi propria**: si applica la stessa commissione di piattaforma prevista per il monitoraggio crypto con la tua chiave (\$0.02 per chiamata). Il tuo fornitore ti fattura direttamente la ricerca sottostante.
* **Le ricerche non riuscite non vengono mai addebitate**; i reinvii riutilizzano l'attribuzione registrata senza una nuova chiamata né un nuovo addebito, e le applicazioni sandbox non vengono mai addebitate.

Quindi un trasferimento in uscita che ha richiesto l'attribuzione costa \$0.02 (Travel Rule) più un addebito di Wallet Verification & Screening; quando entrambi i prodotti sono attivi, la chiamata all'analisi e il relativo addebito avvengono una sola volta.

## Bundle di regole TFR UE

Quattro regole predefinite sono incluse nel bundle `travel_rule_eu_tfr`, pensato specificamente per gli obblighi del regolamento UE TFR.
Come ogni altro [bundle di regole predefinite](https://docs.didit.me/it/transaction-monitoring/rules-library.md), attivalo dalla Business Console in **Transactions → Rules → Library**.

| Regola (`library_key`) | Trigger | Azione |
| - | - | - |
| `tr_eu_mismatch_hold` | Lo stato del trasferimento è `COUNTERPARTY_MISMATCHED_DATA` | `+50` punteggio, transazione impostata su `IN_REVIEW` |
| `tr_eu_unverified_selfhosted_review` | Lo stato del trasferimento è `UNCONFIRMED_OWNERSHIP` e l'importo nella valuta predefinita è almeno `1000` | Transazione impostata su `IN_REVIEW` |
| `tr_eu_vasp_not_found_score` | Lo stato del trasferimento è `COUNTERPARTY_VASP_NOT_FOUND` | `+25` punteggio, con tag `travel-rule-sunrise` |
| `tr_eu_expired_review` | Lo stato del trasferimento è `EXPIRED` | Transazione impostata su `IN_REVIEW` |

Le regole si attivano a ogni transizione rilevante: alla creazione del trasferimento, alla conferma della titolarità, alla risposta relativa al ritiro tramite email e dal processo di gestione delle scadenze. Così un trasferimento che non si risolve mai emerge comunque per la revisione di conformità, invece di essere liquidato in silenzio.

## Perché funziona meglio su un'unica piattaforma

La conformità alla Travel Rule è un problema di identità travestito da problema di pagamenti, e Didit possiede già l'identità:

* **Dati verificati a portata di mano.** Il soggetto di ogni trasferimento è collegato tramite `vendor_data` al profilo KYC che Didit ha verificato in fase di onboarding (OCR del documento, liveness, confronto facciale), quindi puoi costruire `originator_data` a partire da campi verificati sulla stessa piattaforma.
  Per un utente con una verifica KYC approvata, Didit trasmette l'identità verificata e non i valori che hai digitato (vedi [Dati verificati e provenienza](#dati-verificati-e-provenienza)).
* **Biometria di step-up per i trasferimenti rischiosi.** Una [regola](https://docs.didit.me/it/transaction-monitoring/rules.md) può trattenere qualsiasi trasferimento di alto valore finché l'utente non supera un nuovo controllo biometrico a fronte del volto acquisito in fase di onboarding: la risposta più forte possibile alla compromissione dell'account nel momento del prelievo. Vedi l'[esempio completo](https://docs.didit.me/it/transaction-monitoring/sdk-transaction-submission.md#esempio-verifica-biometrica-rafforzata-per-un-prelievo-di-alto-valore).
* **Un unico grafo dei dispositivi.** I trasferimenti inviati tramite SDK portano le stesse informazioni sul dispositivo delle sessioni KYC, quindi "nuovo dispositivo + importo elevato + primo beneficiario" è una sola regola, non un join in un data warehouse.
* **Screening, regole, casi e scambio in un unico posto.** Lo screening dei wallet che attribuisce il VASP controparte è lo stesso che vedono le tue regole e i tuoi analisti: un solo addebito, una sola console, un unico registro di audit.
* **Prezzi pubblicati.** [\$0.02 per scambio in uscita](#prezzi), nessuno scaglione di volume, nessuna chiamata commerciale.

## FAQ

### Come funziona lo scambio

> [accordion] Didit esegue lo scambio tra VASP da sé, oppure registra soltanto i dati della Travel Rule dopo che un'altra rete ha completato l'handshake?
>
> Didit esegue lo scambio in autonomia.
> Quando invii un trasferimento `travelRule`, Didit esegue la ricerca attiva della controparte, invia i dati dell'ordinante e del beneficiario al VASP ricevente sulle reti che li trasportano, e segna il trasferimento come `COMPLETED` solo quando la controparte lo conferma - si tratta di un handshake gestito, non di un registro successivo al regolamento.
> Una risposta della controparte viene elaborata su tutte le reti tranne `TRUST`, che si limita a inviare, quindi un trasferimento su questa rete scade invece di completarsi. Su `GTR`, `VERIFYVASP` e `SYGNA`, Didit legge la risposta dalla rete o interrogandola ogni 5 minuti, e nessuno scambio su queste reti è ancora stato completato con una rete attiva; su `TRP`, una risposta che la controparte non fornisce subito richiede l'host TRP pubblico di Didit, che non è ancora attivo (vedi [Reti della Travel Rule](https://docs.didit.me/it/transaction-monitoring/travel-rule-networks.md)).
> Didit mantiene inoltre il registro completo e lo stato di conformità di ogni scambio (un [ciclo di vita](#ciclo-di-vita) a 13 stati, [webhook](#webhook) e un registro di audit).
> Se preferisci gestire la Travel Rule con il tuo processo, Didit può invece registrare i dati in modo passivo come tuo unico sistema di riferimento (vedi la domanda sulla registrazione passiva qui sotto).
> Entrambe le modalità sono disponibili: lo scambio attivo viene eseguito una volta impostato `is_enabled: true` nelle [impostazioni](#configurazione) (per impostazione predefinita è `false`), e fino ad allora Didit registra i dati in modo passivo.

> [accordion] È una funzionalità nativa di Didit, o dipende da un provider di interoperabilità esterno (Notabene, Sygna, VerifyVASP, TRP)?
>
> È nativa. Didit esegue una propria implementazione del Travel Rule Protocol (TRP), disponibile su `trp.didit.me` una volta attivo l'host pubblico (al momento non risponde, quindi le controparti non possono raggiungerti tramite TRP oggi), e implementa direttamente i protocolli di rete del settore - `GTR` (Global Travel Rule), `TRUST`, `VerifyVASP` e `Sygna Bridge` (supportati nativamente, inclusi IVMS 101 cifrato con ECIES di Sygna e richieste di permesso firmate). Didit non è un rivenditore di un unico livello di interoperabilità di terze parti. Raggiungere una controparte che opera su una specifica rete di adesione avviene necessariamente tramite quella rete - non esiste un unico canale universale nella Travel Rule - ma la scoperta, l'handshake, la verifica e la tenuta delle registrazioni sono tutti eseguiti da Didit.
> Oggi ogni rete richiede una tua adesione, e `TRUST` si limita a inviare: vedi [Panoramica](#overview).

> [accordion] Quali reti e protocolli della Travel Rule supporta Didit?
>
> Implementati in modo nativo e tentati in rigoroso ordine di priorità: `INTERNAL` (entrambi i VASP su Didit), `TRP` (OpenVASP Travel Rule Protocol), `GTR`, `TRUST`, `VerifyVASP`, `Sygna Bridge`, e un fallback `EMAIL` per le controparti senza strumenti.
> Le reti richiedono oggi una tua adesione, `TRUST` si limita a inviare, e la ricezione su una rete non è ancora attiva: vedi [Reti della Travel Rule](https://docs.didit.me/it/transaction-monitoring/travel-rule-networks.md).
> CODE, TRISA, Notabene e Veriscope compaiono nel Marketplace di Didit come riquadri di richiesta di accesso, senza ancora un'integrazione.
> Vedi [Come Didit instrada uno scambio](https://docs.didit.me/it/transaction-monitoring/travel-rule-interoperability.md#come-didit-instrada-un-exchange) per la tabella di instradamento completa, e [Reti della Travel Rule](https://docs.didit.me/it/transaction-monitoring/travel-rule-networks.md) per ciò che ciascuna raggiunge oggi.

> [accordion] Quale rete dovrei usare e mi servono adesioni proprie?
>
> `TRP` è la base che raccomandiamo: non richiede alcuna adesione condivisa - condividere il tuo [Travel Address](#travel-address) permette a qualsiasi VASP che parla TRP di raggiungerti - e quando una controparte è nota solo tramite indirizzo, l'[attribuzione tramite analisi blockchain](#attribuzione-tramite-analisi-blockchain) la instrada su TRP solo se la voce attribuita nella directory ha già un endpoint TRP.
> In uscita, Didit invia su di essa gli asset elencati in [identificatori di asset TRP](#identificatori-di-asset-trp), e una controparte che non risponde subito richiede l'host TRP pubblico di Didit, che non è ancora attivo.
> Per le reti di adesione, scegli in base a dove operano le tue controparti: GTR offre un'ampia copertura globale, TRUST è orientata ai VASP statunitensi, e VerifyVASP (che ora gestisce anche Sygna Bridge) ha una forte copertura in Asia.
> Sì, oggi ti servono adesioni proprie: Didit non detiene ancora un'adesione di piattaforma su queste reti ed è in fase di onboarding come provider.
> Collega la tua adesione in **Marketplace**; non sei vincolato a una sola rete.
> Ricorda che `TRUST` si limita a inviare, quindi un trasferimento su di essa non si completa, e che nessuno scambio su una rete è ancora stato completato con una rete attiva.

> [accordion] Come trova Didit il VASP della controparte quando ho solo un indirizzo?
>
> Tramite una catena di risoluzione: un altro cliente Didit che ha dimostrato il controllo del wallet (la rete `INTERNAL`), la tua [rubrica degli indirizzi dei wallet](#rubrica-degli-indirizzi-wallet) per un Travel Address memorizzato, poi i protocolli e le reti di adesione, e infine l'[attribuzione tramite analisi blockchain](#attribuzione-tramite-analisi-blockchain).
> Se il trasferimento riporta solo un wallet di destinazione, Didit lo risolve con i dati di analisi blockchain per attribuire l'exchange di criptovalute o il servizio di custodia della controparte e lo cataloga nella [directory dei VASP](#directory).
> Il trasferimento viene poi instradato automaticamente solo se quella voce della directory ha già un percorso, come un endpoint `TRP`; altrimenti termina con `COUNTERPARTY_VASP_NOT_FOUND` con il nome della controparte registrato, e puoi reinviarlo quando esiste un percorso, ad esempio dopo aver memorizzato il `travel_address` della controparte nella voce della tua rubrica per quel wallet (per gli asset elencati in [identificatori di asset TRP](#identificatori-di-asset-trp)).

### Prezzi e licenze

> [accordion] Quanto costa la Travel Rule e rientra nel mio piano KYC o di verifica?
>
> La Travel Rule è un prodotto separato a consumo.
> Non è incluso nella verifica dell'identità.
> Costa \*\*$0.02 per scambio in uscita avviato** ([prezzi pubblicati](#prezzi), nessuno scaglione di volume, nessuna chiamata commerciale).
>         Quando l'instradamento richiede una ricerca di analisi blockchain per identificare il VASP della controparte, tale ricerca viene addebitata una volta alla [tariffa di attribuzione](#prezzi-dell’attribuzione): da $0.15 in modalità gestita, oppure \$0.02 con una chiave di un provider esistente.
> Non viene riaddebitata se il monitoraggio delle crypto ha già analizzato lo stesso wallet.
> Un trasferimento sotto la tua soglia, oppure uno registrato con la Travel Rule disattivata, viene fatturato come Transaction Screening; i trasferimenti in entrata, come i trasferimenti che Didit genera sul lato del beneficiario, non sono soggetti alla tariffa della Travel Rule.

> [accordion] Verrò addebitato due volte quando Travel Rule e il monitoraggio crypto girano insieme?
>
> No.
> Una transazione `travelRule` viene fatturata su una sola riga: la tariffa Travel Rule (\$0.02) quando avvia uno scambio in uscita, altrimenti il normale Transaction Screening. La ricerca di analisi blockchain viene addebitata una volta: se il monitoraggio delle crypto ha già analizzato il wallet di destinazione della transazione, l'[attribuzione](#attribuzione-tramite-analisi-blockchain) riutilizza quel risultato memorizzato senza costi aggiuntivi.
> I trasferimenti in entrata che Didit genera sul lato del beneficiario non vengono mai fatturati con la tariffa Travel Rule.

> [accordion] Didit può fornire documentazione o una dichiarazione di capacità per la licenza VASP o il fascicolo del regolatore?
>
> Sì. Le capacità di KYT e monitoraggio delle transazioni, Screening AML e delle sanzioni, analisi del rischio dei wallet tramite analisi blockchain e Travel Rule sono tutte documentate pubblicamente su docs.didit.me, e puoi citare queste pagine in un fascicolo normativo. Per una dichiarazione formale delle capacità del prodotto, personalizzata per una specifica domanda - ad esempio una domanda di licenza VASP AIFC/AFSA, MiCA o di altro tipo - contatta il team di Didit che gestisce il tuo account indicando il formato richiesto dal tuo regolatore.

### Operazioni e dati

> [accordion] Cosa succede ai trasferimenti sotto la mia soglia?
>
> Vengono risolti immediatamente con `NOT_APPLICABLE`: non viene tentato alcun canale e nessun dato identificativo lascia Didit.
> La transazione viene fatturata come normale Transaction Screening, non con la tariffa Travel Rule.
> Didit confronta la soglia con l'importo convertito nella valuta predefinita della tua applicazione.
> Se Didit non riesce a convertire l'importo, la soglia non viene applicata e il trasferimento viene eseguito.
> Il regolamento TFR dell'UE non prevede un minimo, quindi i CASP UE dovrebbero mantenere `threshold_amount` a `0.00`.

> [accordion] Cosa succede se la controparte non risponde mai?
>
> Il trasferimento resta in `AWAITING_COUNTERPARTY` fino allo scadere di `confirmation_timeout_hours`; poi un processo di controllo lo sposta in `EXPIRED` e applica il tuo `timeout_outcome` alla transazione sottostante: `HOLD` per la revisione, `REJECT` per rifiutarla oppure `PROCEED` per lasciarla invariata. La regola predefinita `tr_eu_expired_review` segnala inoltre ai tuoi analisti ogni scadenza. Una controparte che non riceve affatto il messaggio è un caso diverso: Didit ritenta l'invio e, dopo il sesto tentativo fallito, il trasferimento passa a `COUNTERPARTY_VASP_NOT_REACHABLE` (vedi [Consegna e nuovi tentativi](#consegna-e-nuovi-tentativi)).

> [accordion] La mia controparte non ha alcuno strumento Travel Rule. Posso comunque essere conforme?
>
> Sì: è il canale `EMAIL`. Il referente di compliance della controparte riceve un link monouso per il recupero e può confermare o rifiutare lo scambio da una pagina ospitata, senza account Didit, senza chiave API e senza alcuna integrazione. Per i depositi già regolati prima che fosse possibile qualsiasi scambio, usa la [registrazione sunrise dopo il deposito](#registrazione-postuma-del-deposito-sunrise).

> [accordion] Come funzionano i prelievi verso il wallet dell'utente?
>
> Dichiara la destinazione come in autocustodia (`payment_method.method_type: "unhosted_wallet"`). Didit salta l'instradamento verso i VASP e raccoglie invece la prova che il tuo cliente controlla il wallet, tramite firma di un messaggio, test Satoshi, screenshot o autodichiarazione, attraverso il [widget di verifica della proprietà del wallet](https://docs.didit.me/it/transaction-monitoring/wallet-ownership-widget.md). Questo è l'obbligo del regolamento TFR dell'UE sui wallet in autocustodia, in forma di API.

> [accordion] I dati personali della controparte sono protetti durante lo scambio?
>
> Sì.
> Finché la proprietà del wallet non è confermata dalla tua parte, i dati personali della controparte su un trasferimento in entrata sono mascherati, sia nell'oggetto del trasferimento sia nel soggetto controparte della transazione (vedi [Dati della controparte mascherati](#dati-della-controparte-mascherati)).
> Le pagine di ritiro via email mostrano solo il riepilogo del trasferimento (nome del VASP ordinante, importo, wallet di destinazione), mai i payload contenenti i dati personali.
> Gli scambi sui canali avvengono tramite HTTPS e le reti (`GTR`, `TRUST`, `VERIFYVASP`, `SYGNA`) cifrano inoltre il payload IVMS con la chiave pubblica del VASP ricevente.

> [accordion] Gestisco già la conformità Travel Rule con un mio processo. Posso limitarmi a registrarla?
>
> Sì. Con Travel Rule disattivato, qualsiasi `travel_rule_details` che invii (incluso uno `status` fornito dal chiamante, nel formato attuale o legacy) viene registrato in modo passivo sulla transazione: non viene avviato alcun canale e non si negozia nulla. Puoi usarlo per recuperare dati storici o per gestire un tuo processo mantenendo un unico sistema di registrazione.

> [accordion] Come posso testare tutto prima di andare in produzione?
>
> Usa un'applicazione sandbox con Travel Rule attivo. La sandbox ignora regole, fatturazione e i webhook `transaction.created` e `transaction.status.updated`, e ogni scambio **in uscita** va al [Didit Test VASP](https://docs.didit.me/it/transaction-monitoring/travel-rule-sandbox.md) sul canale `TEST_VASP`, che risponde all'interno di Didit con lo scenario che scegli: accettazione, rifiuto, mancata corrispondenza del nome, non raggiungibile, timeout o wallet in autocustodia. Ricevi webhook `travel_rule.status.updated` contrassegnati con `environment: sandbox`, e nessun messaggio raggiunge una controparte reale.
> Per i trasferimenti **in entrata**, fai inviare al test VASP un trasferimento con [Trigger Test VASP Inbound Transfer](https://docs.didit.me/it/management-api/travel-rule/trigger-test-vasp-inbound.md), oppure registrane uno con `POST /v3/travel-rule/inbound/`; entrambi vengono decisi in base alla rubrica degli indirizzi dei tuoi wallet: `ON_HOLD`, `UNCONFIRMED_OWNERSHIP`, `COUNTERPARTY_MISMATCHED_DATA`, oppure `COMPLETED` seguito da `FINISHED`.
> Per uno scambio a due parti con un'altra applicazione reale, usa due tue applicazioni **di produzione** sul canale `INTERNAL`: quella ricevente deve essere individuabile e dimostrare il controllo del wallet di destinazione con un messaggio firmato o con un deposito di prova.

## Prossimi passi

> [card] [Widget per la proprietà del wallet](https://docs.didit.me/it/transaction-monitoring/wallet-ownership-widget.md)
>
> Dimostra che un cliente controlla un wallet tramite firma, test Satoshi, screenshot o autodichiarazione.

> [card] [Interoperabilità](https://docs.didit.me/it/transaction-monitoring/travel-rule-interoperability.md)
>
> Gli endpoint rivolti alle controparti che gli altri VASP usano per raggiungerti: TRP, callback, ritiro via email, sunrise.

> [card] [Reti](https://docs.didit.me/it/transaction-monitoring/travel-rule-networks.md)
>
> Cosa raggiunge oggi ciascun canale e ciascuna rete, e quali richiedono ancora un'adesione.

> [card] [Test in sandbox](https://docs.didit.me/it/transaction-monitoring/travel-rule-sandbox.md)
>
> Prova ogni esito con il Didit Test VASP prima di andare in produzione.

> [card] [Invio delle transazioni](https://docs.didit.me/it/transaction-monitoring/transactions.md)
>
> Come includere i dati Travel Rule nel payload di Create Transaction.

> [card] [Libreria delle regole](https://docs.didit.me/it/transaction-monitoring/rules-library.md)
>
> Il catalogo completo delle regole predefinite, incluso il pacchetto Travel Rule.

> [card] [Webhook](https://docs.didit.me/it/integration/webhooks.md)
>
> Iscriviti a travel\_rule.status.updated e a tutte le altre famiglie di eventi.

> [card] [Guida alla console](https://docs.didit.me/it/transaction-monitoring/console.md)
>
> Visualizzare lo stato Travel Rule nella vista di dettaglio della transazione.


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