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

# Widget de preuve de propriété de portefeuille Travel Rule

> Widget Didit hébergé prouvant le contrôle d'un portefeuille crypto par signature, test Satoshi, capture d'écran ou déclaration, pour la Travel Rule.

Le widget de propriété du portefeuille est une page hébergée qui prouve qu'un de vos clients contrôle une adresse de portefeuille crypto spécifique. Selon le règlement européen TFR, un VASP doit vérifier la propriété d'un portefeuille auto-hébergé (non hébergé) avant d'envoyer des fonds vers ce portefeuille ou depuis celui-ci, au-delà du seuil sunrise. Le widget permet à Didit de recueillir cette preuve sans que vous ayez à développer vous-même les flux de signature.

Une preuve vérifiée marque l'[entrée du carnet d'adresses de portefeuilles](https://docs.didit.me/fr/transaction-monitoring/travel-rule.md#carnet-d’adresses-de-portefeuilles) correspondante avec `is_ownership_verified: true`, ce qui permet à un [transfert Travel Rule](https://docs.didit.me/fr/transaction-monitoring/travel-rule.md) lié de sortir de l'état `UNCONFIRMED_OWNERSHIP`.

## Quand Didit le crée pour vous

Vous avez rarement besoin de créer une session vous-même.
Lorsque `auto_wallet_verification` est activé dans vos [paramètres Travel Rule](https://docs.didit.me/fr/transaction-monitoring/travel-rule.md#configuration) (valeur par défaut), Didit crée automatiquement une session de widget à la création de la transaction, chaque fois qu'un transfert nécessite une preuve de contrôle du portefeuille par l'utilisateur final :

* Le transfert est en `UNCONFIRMED_OWNERSHIP` : le portefeuille de la contrepartie a été déclaré [auto-hébergé](https://docs.didit.me/fr/transaction-monitoring/travel-rule.md#portefeuilles-auto-hébergés-déclarés) lors de la soumission.
* Le transfert est sortant et en `COUNTERPARTY_VASP_NOT_FOUND` : aucun VASP de contrepartie n'a pu être identifié, la preuve de propriété est donc la seule voie restante pour mener le transfert à terme.

La session créée automatiquement est renvoyée dans le bloc `action_required` de la transaction (`type: "wallet_ownership"`, avec l'`url` à ouvrir), et les SDK la lancent automatiquement lors de la [soumission côté client](https://docs.didit.me/fr/transaction-monitoring/sdk-transaction-submission.md#actions-requises-de-l’utilisateur).
Les transferts entrants que Didit crée pour vous (un enregistrement sunrise, une requête `TRP` entrante ou la portion entrante du rail `INTERNAL`) ne reçoivent jamais de session générée automatiquement, même lorsqu'ils passent en `UNCONFIRMED_OWNERSHIP`.
Créez une session manuellement avec `POST /v3/travel-rule/widget-session/` lorsque vous souhaitez pré-vérifier un portefeuille avant qu'un transfert n'existe, lorsque `auto_wallet_verification` est désactivé, ou pour l'un de ces transferts entrants.

## Ce que cela prouve

Le widget propose jusqu'à quatre méthodes de preuve. Les méthodes qui apparaissent dépendent de la façon dont vous avez créé la session et de vos [paramètres Travel Rule](https://docs.didit.me/fr/transaction-monitoring/travel-rule.md#configuration) :

| Méthode | Fonctionnement | Quand elle est proposée |
| - | - | - |
| `MESSAGE_SIGNING` | Le client signe avec son portefeuille une chaîne de défi émise par Didit. Sont pris en charge les portefeuilles EVM, Solana, Bitcoin et Tron (pour Bitcoin : adresses legacy, SegWit imbriqué, SegWit natif et Taproot). Didit vérifie la signature par rapport à l'adresse, et une signature faite avec un compte différent de celui à vérifier est rejetée, avec une invite claire à changer de compte. Les comptes à contrat intelligent EVM (portefeuilles intelligents ERC-4337) peuvent aussi signer : Didit demande au contrat du compte, sur la chaîne où le portefeuille est déclaré, si la signature est valide (ERC-1271). Pour un compte qui n'est pas encore déployé, Didit vérifie la signature ERC-6492 renvoyée par le portefeuille, sans déployer le compte ni envoyer de transaction. Les comptes à contrat intelligent sont vérifiés sur toutes les chaînes EVM prises en charge. Voir [Contrat de vérification de la signature de message](#contrat-de-vérification-de-la-signature-de-message) ci-dessous. Les portefeuilles installés dans le navigateur du client sont détectés grâce aux protocoles EIP-6963 et Wallet Standard, si bien que chaque extension apparaît comme une option de signature distincte. Le couplage d'une application de portefeuille mobile distincte, par exemple par QR code, n'est pas disponible aujourd'hui. | Toujours, pour les familles de chaînes prises en charge. |
| `SATOSHI_TEST` | Le client envoie depuis son portefeuille un très petit montant on-chain vers une adresse de dépôt que vous contrôlez. Le service de surveillance de Didit vérifie l'expéditeur (pour un compte à contrat intelligent EVM, le compte lui-même, y compris lorsqu'un bundler ERC-4337 soumet la transaction), le montant, et la confirmation du dépôt on-chain. La preuve est ensuite complétée automatiquement dès que le dépôt est confirmé. Voir [Contrat de vérification du test Satoshi](#contrat-de-vérification-du-test-satoshi) ci-dessous. | Uniquement lorsque vous transmettez un `satoshi_deposit_address` au moment de la création et que la chaîne est une chaîne EVM, Bitcoin ou Solana. Elle n'est donc jamais proposée sur une session créée automatiquement. |
| `SCREENSHOT` | Le client téléverse une capture d'écran du portefeuille affichant l'adresse (JPEG, PNG ou WebP, jusqu'à 10 Mo). Contrairement aux autres méthodes, elle ne se vérifie jamais automatiquement : votre équipe de conformité l'examine dans la file d'attente d'examen des captures d'écran ([`GET /v3/travel-rule/wallet-proofs/`](https://docs.didit.me/fr/management-api/travel-rule/list-wallet-proofs)), puis l'approuve ou la rejette ([`POST .../decision/`](https://docs.didit.me/fr/management-api/travel-rule/decide-wallet-proof)). Votre équipe de conformité peut aussi confirmer le transfert depuis l'onglet **Travel Rule** de la transaction dans la console, ou via [`POST .../travel-rule/ownership/`](https://docs.didit.me/fr/management-api/travel-rule/confirm-ownership) (pour un transfert en `UNCONFIRMED_OWNERSHIP` ou un transfert entrant en attente). | Uniquement lorsque `allow_screenshot_proof` vaut `true` dans vos paramètres. |
| `SELF_DECLARATION` | Le client atteste la propriété sans preuve cryptographique, en dernier recours et lorsque la juridiction le tolère. | Uniquement lorsque `allow_self_declaration` vaut `true` et que votre [`ownership_validation_mode`](https://docs.didit.me/fr/transaction-monitoring/travel-rule#modes-de-validation-de-la-propriété) accepte une déclaration pour le transfert lié : jamais en `FULL`, et en `SIMPLIFIED` uniquement en dessous de `simplified_validation_threshold`. Initier une déclaration que le mode n'accepte pas renvoie `403`. |

### Contrat de vérification de la signature de message

La soumission de la signature renvoie `200` avec `status: "VERIFIED"` dès qu'elle prouve le contrôle du portefeuille.
Elle renvoie `400` et laisse la preuve ouverte, afin que le client puisse signer à nouveau, avec l'une de ces valeurs de `code` :

| `code` | Signification |
| - | - |
| `SIGNATURE_INVALID` | La signature ne prouve pas le portefeuille : un autre compte ou une autre clé a signé, ou le message diffère. Pour un compte à contrat intelligent, son contrat a répondu que la signature ne lui appartient pas. |
| `SIGNATURE_UNSUPPORTED_SCHEME` | Le portefeuille a signé dans un format que Didit ne vérifie pas, par exemple une signature multisignature Bitcoin ou une signature complète BIP-322. |
| `SIGNATURE_LOOKUP_FAILED` | Le portefeuille est peut-être un compte à contrat intelligent, et sa chaîne n'a pas pu être vérifiée pour le moment. La preuve n'est jamais validée sur cette réponse ; signer à nouveau la vérifie de nouveau. |

### Contrat de vérification du test Satoshi

La vérification d'un dépôt de test Satoshi est asynchrone, car la transaction doit être visible on-chain, puis confirmée.
La soumission du `txid` du dépôt renvoie `200` avec `status: "PENDING"` tant que le dépôt n'est pas encore confirmé on-chain. Le `txid` est conservé, et non abandonné.
Elle renvoie `200` avec `status: "VERIFIED"` dès que le dépôt est confirmé.
Elle renvoie `400` avec `status: "REJECTED"` pour un dépôt réellement incorrect : envoyé depuis un autre portefeuille, montant différent de celui attendu vers l'adresse de dépôt, antérieur au défi, ou transaction ayant déjà prouvé un autre portefeuille. La preuve est close, et le client peut en démarrer une nouvelle tant que la session dispose encore de tentatives.
Un dépôt qui n'est pas encore indexé renvoie également `200` avec `status: "PENDING"`, et un échec de recherche côté Didit renvoie `400` avec le code `DEPOSIT_LOOKUP_FAILED`. Dans les deux cas, la preuve reste ouverte et Didit continue de vérifier.
Elle renvoie `410` si la fenêtre de test expire avant qu'un dépôt valide ne soit constaté.

Une fois un `txid` soumis, une tâche en arrière-plan revérifie le dépôt en attente toutes les cinq minutes et complète la preuve après la confirmation de la transaction. Le client n'a donc pas besoin de soumettre à nouveau le `txid`.
Lorsque vous transmettez un `satoshi_deposit_address`, le `expires_at` de la session du widget est prolongé à au moins la fenêtre de test Satoshi de 24 heures, afin que le dépôt ait le temps de se confirmer avant l'expiration de la session elle-même.

## Déroulement

**1. Générer une session de widget**

Appelez `POST /v3/travel-rule/widget-session/` avec le portefeuille que vous devez faire vérifier. Vous pouvez éventuellement le lier à un transfert afin que celui-ci avance automatiquement une fois la propriété du portefeuille prouvée.

**2. Ouvrir l'URL renvoyée**

Envoyez votre client à l'`url` de la réponse. Il y réalise une preuve sans compte Didit ni clé API : le token présent dans l'URL sert d'authentification.

**3. Détecter la fin du processus**

Lorsqu'une preuve est vérifiée, le widget marque l'entrée du carnet d'adresses comme vérifiée et, si la session est liée à un transfert, fait avancer celui-ci. Surveillez `travel_rule.status.updated` (pour les transferts liés) ou interrogez le contexte du widget.

### Générer une session de widget

Cet exemple lie la session au [transfert déclaré vers un portefeuille auto-hébergé](https://docs.didit.me/fr/transaction-monitoring/travel-rule.md#portefeuilles-auto-hébergés-déclarés) du guide Travel Rule, de sorte que `wallet_address` correspond à l'adresse de destination de ce transfert.
Une session liée à un transfert n'accepte que les preuves portant sur l’adresse de la contrepartie de ce transfert.

```bash theme={null}
curl -X POST https://verification.didit.me/v3/travel-rule/widget-session/ \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "wallet_address": "0xd3b62acb76fb27a7f8961ec40fa11746b113aca9",
    "chain": "ETH",
    "holder_name": "Jane Doe",
    "vendor_data": "user-042",
    "transaction_id": "99999999-aaaa-bbbb-cccc-dddddddddddd",
    "satoshi_deposit_address": "0x71C7656EC7ab88b098defB751B7401B5f6d8976F",
    "callback_url": "https://yourapp.example/wallet-verified",
    "expires_in_minutes": 60
  }'
```

| Champ | Type | Description |
| - | - | - |
| `wallet_address` | chaîne | L'adresse à vérifier. |
| `chain` | chaîne | Identifiant de la blockchain de l'adresse (par exemple `ETH`, `BTC`, `SOL`). Utilisez le même token que celui de vos transferts (`ETH`, et non `ethereum`) : le widget enregistre l'entrée du carnet d'adresses avec ce `chain`, et un transfert sur une autre chaîne ne lui correspond pas. La signature de message nécessite une chaîne reconnue par Didit. |
| `holder_name` | chaîne | Nom du titulaire du portefeuille, utilisé pour la correspondance du nom du bénéficiaire. |
| `vendor_data` | chaîne | Votre identifiant interne du titulaire, repris dans l'entrée du carnet d'adresses créée. |
| `transaction_id` | chaîne (uuid) | Facultatif. UUID de transaction Didit d'un transfert Travel Rule à faire avancer lorsque la preuve est vérifiée ; un UUID inconnu renvoie `404`, et une preuve portant sur une autre adresse que celle de la contrepartie du transfert est rejetée avec `400`. Omettez ce champ pour vérifier un portefeuille indépendamment. |
| `satoshi_deposit_address` | chaîne | Facultatif. Une adresse de dépôt que vous contrôlez ; la fournir active la méthode `SATOSHI_TEST`. |
| `callback_url` | chaîne | Facultatif. Adresse vers laquelle le widget renvoie le client après la fin du processus. |
| `expires_in_minutes` | entier | Facultatif. Durée de validité du lien généré, en minutes, de `5` à `10080` (par défaut `60`) ; automatiquement portée à au moins la fenêtre de test Satoshi de 24 heures lorsque vous fournissez un `satoshi_deposit_address`. |

```json theme={null}
{
  "widget_session_id": "77777777-8888-9999-aaaa-bbbbbbbbbbbb",
  "token": "3s9x...urlsafe",
  "url": "https://verify.didit.me/wallet-ownership/3s9x...urlsafe",
  "expires_at": "2026-07-07T13:00:00Z"
}
```

Ouvrez toujours l'`url` renvoyée dans la réponse telle quelle : ne la construisez pas vous-même.

### Ouvrir l'URL renvoyée

> [!WARNING]
>
> **Le widget n'est disponible que sur le web dans cette version. Ouvrez l'`url` dans le navigateur du système ou dans un onglet personnalisé - jamais dans une webview du SDK mobile Didit.**
>
> La signature de message fonctionne avec les portefeuilles installés dans le navigateur du client, que le widget détecte grâce aux protocoles EIP-6963 et Wallet Standard.
> L'appairage d'une application de portefeuille mobile distincte, par exemple par QR code, n'est pas disponible actuellement : le widget ne transmet donc pas le processus à une autre application.
> Une webview intégrée à l'application, telle que la webview des SDK Didit Web, Flutter, React Native, iOS et Android, **ne peut pas accéder aux portefeuilles du navigateur du client**. Un widget ouvert dans une telle webview empêche le client de signer.
>
> Sur mobile, ouvrez l'`url` avec le navigateur du système (`SFSafariViewController` / Chrome Custom Tabs, ou le navigateur par défaut) au lieu de l'afficher dans une webview. Sur le web, un onglet ou une fenêtre popup classique convient.

### Détecter la fin du processus

Le widget expose un endpoint de lecture public, identifié par le token. Interrogez-le pour suivre la progression, ou appuyez-vous sur les webhooks lorsque la session est liée à un transfert :

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

```json theme={null}
{
  "vasp_name": "Origin CASP SL",
  "wallet_address": "0xd3b62acb76fb27a7f8961ec40fa11746b113aca9",
  "chain": "ETH",
  "holder_name": "Jane Doe",
  "allowed_methods": ["MESSAGE_SIGNING", "SCREENSHOT", "SATOSHI_TEST", "SELF_DECLARATION"],
  "transfer_status": "UNCONFIRMED_OWNERSHIP",
  "callback_url": "https://yourapp.example/wallet-verified",
  "expires_at": "2026-07-07T13:00:00Z",
  "completed_at": null,
  "proofs": [
    {
      "proof_id": "88888888-9999-aaaa-bbbb-cccccccccccc",
      "method": "SATOSHI_TEST",
      "status": "PENDING",
      "wallet_address": "0xd3b62acb76fb27a7f8961ec40fa11746b113aca9",
      "chain": "ETH",
      "deposit_address": "0x71C7656EC7ab88b098defB751B7401B5f6d8976F",
      "expected_amount": "0.000042817305521963",
      "expires_at": "2026-07-07T13:05:00.412731+00:00",
      "created_at": "2026-07-06T13:05:00.412731Z"
    }
  ],
  "customization": null
}
```

* `completed_at` prend une valeur non nulle dès qu'une preuve est vérifiée.
* Chaque entrée de `proofs` contient les champs nécessaires à sa méthode : une preuve `SATOSHI_TEST` ajoute `deposit_address`, `expected_amount` et son propre `expires_at` ; une preuve `MESSAGE_SIGNING` ajoute `challenge`, la chaîne que le client signe.
* Une preuve `SATOSHI_TEST` peut rester à `status: "PENDING"` tant que son dépôt est visible on-chain mais non confirmé, sans aucune action requise de votre part ni de celle du client : voir [contrat de vérification du test Satoshi](#contrat-de-vérification-du-test-satoshi) ci-dessus.
* Lorsque la session a été générée avec un `transaction_id`, la vérification de la preuve fait avancer le transfert lié, et, sur une application en production, le webhook [`travel_rule.status.updated`](https://docs.didit.me/fr/integration/webhooks#types-d’événements) est déclenché.
  Privilégiez le webhook plutôt que l'interrogation.
  Une demande `TRP` entrante est approuvée et renvoyée à l'expéditeur, et passe à `COMPLETED` une fois cette approbation transmise.
  Tout autre transfert en `UNCONFIRMED_OWNERSHIP` (ou un transfert entrant `ON_HOLD`) passe à `COMPLETED`, ou à `COUNTERPARTY_MISMATCHED_DATA` lorsque le nom du bénéficiaire ne correspond pas à celui du titulaire du portefeuille, et un dépôt sunrise réglé qui aboutit passe à `FINISHED`.
  Un transfert sortant en `COUNTERPARTY_VASP_NOT_FOUND` passe à `COMPLETED`.
* Une preuve `SCREENSHOT` reste à `status: "PENDING"` dans ce contexte, même après que vous avez confirmé la propriété.
  Vous l'approuvez avec [`POST .../travel-rule/ownership/`](https://docs.didit.me/fr/transaction-monitoring/travel-rule#confirmation-de-la-propriété-du-portefeuille), qui n'accepte que les transferts en attente de confirmation de propriété.
  Une capture d'écran n'a donc aucun chemin d'approbation sur une session sans transfert lié, ou sur une session liée à un transfert sortant en `COUNTERPARTY_VASP_NOT_FOUND` : désactivez `allow_screenshot_proof` si ces sessions ne doivent pas proposer cette option.
* Après une preuve rejetée, la session offre une nouvelle tentative tant qu'il en reste.
  `max_attempts`, `attempts_used` et `attempts_remaining` indiquent le nombre de tentatives, une preuve rejetée contient `rejection_reason`, et lorsque `attempts_remaining` vaut `0`, toute nouvelle preuve renvoie `409` : vous devez alors générer une nouvelle session.
* L'endpoint de contexte renvoie `404` pour un token inconnu et `410` lorsque la session a expiré sans être terminée.

> [!NOTE]
>
> Il n'existe aucune dépendance à usage unique ici : le widget et votre backend convergent vers le même état durable (l'entrée vérifiée du carnet d'adresses et le statut du transfert). La situation reste donc toujours récupérable en cas de webhook perdu ou d’onglet fermé, en relisant le transfert ou le contexte du widget.

## Localisation et personnalisation

Le widget s'affiche en **54 langues**, selon le chemin de langue du lien (ou la langue par défaut du navigateur).

Lorsque la marque blanche est activée pour votre application, le widget reprend automatiquement la personnalisation de votre parcours de vérification : logo, couleurs de marque, style des boutons et du panneau, police personnalisée, favicon et nom public de votre application dans le titre.
Aucune configuration distincte : la même personnalisation que celle définie pour les sessions KYC s'applique ici.

Un utilisateur qui revient sur un lien déjà terminé revoit l'écran de fin ; si vous avez transmis un `callback_url`, le widget le renvoie vers cette URL.
Les liens expirés affichent un écran d'expiration personnalisé qui invite l'utilisateur à demander un nouveau lien.
Générez une nouvelle session avec `POST /v3/travel-rule/widget-session/` pour cet utilisateur : renvoyer un transfert avec `action: "resend"` n'en crée pas une.

## Prochaines étapes

> [card] [Travel Rule](https://docs.didit.me/fr/transaction-monitoring/travel-rule.md)
>
> Le cycle de vie complet des échanges, les rails, les paramètres et les flux de réception.

> [card] [Carnet d'adresses des portefeuilles](https://docs.didit.me/fr/transaction-monitoring/travel-rule.md#carnet-d’adresses-de-portefeuilles)
>
> Enregistrez les portefeuilles que vous contrôlez afin que les transferts entrants soient associés à ces portefeuilles.

> [card] [Webhooks](https://docs.didit.me/fr/integration/webhooks.md)
>
> Abonnez-vous à travel\_rule.status.updated pour réagir lorsqu'une preuve fait progresser un transfert.

> [card] [SDK natifs](https://docs.didit.me/fr/integration/native-sdks/overview.md)
>
> Ouvrez l'URL du widget dans le navigateur système, et non dans la webview du SDK.


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