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

# Données de test sandbox : scénarios et valeurs magiques

> Testez Didit dans le sandbox : scénarios, valeurs magiques, endpoint arm, documents et codes OTP pour des résultats déterministes, sans PII ni facturation.

Le **sandbox** de Didit est l'équivalent des cartes de test de Stripe ou des modèles de documents de Sumsub : il vous permet de reproduire n'importe quel résultat de vérification de manière déterministe, sans faire appel à de vrais fournisseurs, sans utiliser de véritables données personnelles et sans toucher à votre solde.

> [!NOTE]
>
> La source de référence de ces données est `serialize_catalog()` dans le service de vérification, exposé en direct à `GET /v1/sandbox/scenarios/`. Une copie testée contre les dérives est générée dans `docs/sandbox/SANDBOX_REFERENCE.md` du dépôt `service-didit-verification` via `pipenv run python scripts/generate_sandbox_reference.py`. Cette page reprend cette référence : si quelque chose semble obsolète ici, fiez-vous toujours à l'endpoint du catalogue en direct. Cet endpoint nécessite une authentification : envoyez votre clé API (`x-api-key`) comme pour n'importe quel autre appel, ou un token de session si vous le consultez depuis une session en cours.

## Modèle d'environnement

Le **sandbox** est un **mode par application** (`ApplicationDetail.mode == SANDBOX`), selon le même principe que le mode test de Stripe. Pendant qu'une session s'exécute sous une application sandbox :

* Tous les fournisseurs externes (OCR, AML, correspondance faciale, détection du vivant, NFC, téléphone, e-mail, IP, justificatif de domicile, validation en base de données, Document AI) sont **simulés** : aucun tiers n'est jamais sollicité.
* **La détection du vivant fonctionne exactement comme en production.** Un workflow de détection active du vivant exécute la capture active réelle dans le sandbox, que ce soit dans le flux hébergé ou via la transmission web des SDK natifs, afin que vous puissiez tester l'expérience que vos utilisateurs obtiendront. Seul le *résultat* de la détection du vivant est simulé, par le scénario ou la valeur magique, et le rapport enregistre la méthode configurée dans votre workflow.
* **Les domaines personnalisés sont réservés à la production.** Une application sandbox ne peut pas ajouter de [domaine personnalisé](https://docs.didit.me/fr/console/custom-domain.md) : les sessions sandbox fonctionnent toujours sur le domaine par défaut de la page de vérification hébergée.
* Les sessions ne sont **jamais facturées** et la vérification du solde est ignorée.
* Un quota par application de 500 créations de session par 24 h est appliqué.
* Les webhooks contiennent `"environment": "sandbox"` (les sessions en production contiennent `"environment": "live"`).
* Le flux hébergé expose l'environnement de la session afin que l'interface puisse avertir les utilisateurs de ne pas téléverser de vraies données personnelles.
* **Les résultats ne dépendent jamais des pixels** : les données extraites et les statuts proviennent du scénario ou de la valeur magique. Les médias capturés eux-mêmes (documents, selfie, vidéo, fichiers de justificatif de domicile) sont effectivement stockés, exactement comme pour une session en production.

## Transaction Monitoring in sandbox

Sandbox est **orienté session** : il simule les fournisseurs qu'une session de vérification appellerait. La Surveillance des transactions n'a pas de fournisseur à simuler, donc une application sandbox suit une autre voie : la transaction est enregistrée, mais **rien de ce qui décide, filtre, notifie ou facture ne s'exécute sur elle**.

Une transaction créée sur une application sandbox est enregistrée et renvoyée comme d'habitude, et aucun des points suivants ne lui arrive :

* **Aucune évaluation de règles.** `rule_runs` est vide, quel que soit le mode de vos règles. Une règle `ACTIVE` sur une application sandbox ne se déclenche jamais : la transaction reste `APPROVED` avec un score de `0`, et aucune alerte ni aucun dossier n'est ouvert.
* **Aucun filtrage AML ni filtrage des portefeuilles.** `provider_results` est vide, même pour les transactions crypto sur une application où la surveillance est activée.
* **Aucun webhook.** Ni `transaction.created` ni `transaction.status.updated` ne sont livrés pour une transaction sandbox.
* **Aucune facturation.** Un événement d'usage est enregistré au prix de `0.0000` et votre solde n'est pas modifié.

Chaque réponse de transaction contient un champ `environment` (`"live"` ou `"sandbox"`), de sorte qu'un `rule_runs` vide n'est jamais ambigu : `"sandbox"` signifie que les règles n'ont pas été évaluées, et non qu'aucune ne correspond. La Business Console indique la même chose dans la carte *Risques et décision* de la transaction, au lieu d'un simple « Aucune règle évaluée ».

> [!NOTE]
>
> **Travel Rule est la seule exception à « rien ne s'exécute ».** Sur une application où Travel Rule est activée, une transaction `travelRule` en sandbox exécute quand même le moteur d'échange : l'enregistrement du transfert est créé et passe par ses statuts.
> Ce que le sandbox ne fait jamais, c'est communiquer avec quiconque en dehors de Didit.
> Sa seule contrepartie est le [Didit Test VASP](https://docs.didit.me/fr/transaction-monitoring/travel-rule-sandbox.md), intégré à la plateforme : aucun message de conformité n'atteint un VASP contrepartie réel, quel que soit le canal (`TRP`, une adhésion à un réseau que vous avez connectée, e-mail ou `INTERNAL`), le filtrage de l'attribution du VASP contrepartie est ignoré, et une annulation n'envoie rien à la contrepartie.
> Les webhooks `travel_rule.status.updated` sont livrés, marqués `"environment": "sandbox"`.
>
> **Sortant** : une transaction `travelRule` que vous soumettez.
> La vérification du `threshold_amount` s'effectue en premier. En sandbox, elle ne s'applique que si vous envoyez `transaction_details.amount_in_default_currency`, car le sandbox ne convertit pas les devises : sans ce champ, chaque transfert sandbox dépasse le seuil.
> Un transfert sans réponse expire après `confirmation_timeout_hours`, et votre `timeout_outcome` s'applique alors à la transaction.
> Au-delà du seuil, la vérification du portefeuille auto-hébergé déclaré s'applique normalement : un transfert vers un [portefeuille auto-hébergé déclaré](https://docs.didit.me/fr/transaction-monitoring/travel-rule.md#portefeuilles-auto-hébergés-déclarés) passe à `UNCONFIRMED_OWNERSHIP` sans rien être envoyé, et vous pouvez le finaliser en sandbox avec le [widget de confirmation de propriété du portefeuille](https://docs.didit.me/fr/transaction-monitoring/wallet-ownership-widget.md), ou via [confirmer la propriété](https://docs.didit.me/fr/management-api/travel-rule/confirm-ownership.md) lorsque le portefeuille de destination figure déjà dans votre carnet d'adresses de portefeuilles.
> Tout autre transfert au-delà du seuil est envoyé au Didit Test VASP sur le canal `TEST_VASP`, qui y répond au sein de Didit avec le scénario que vous choisissez selon le portefeuille ou le nom du bénéficiaire : il est finalisé, refusé, présente une incohérence, passe à `COUNTERPARTY_VASP_NOT_REACHABLE`, expire (votre `timeout_outcome` s'applique alors à la transaction) ou attend la vérification de la propriété du portefeuille.
> Consultez [Tester Travel Rule en sandbox](https://docs.didit.me/fr/transaction-monitoring/travel-rule-sandbox.md) pour chaque scénario.
>
> **Entrant** : `POST /v3/travel-rule/inbound/`. L'enregistrement n'envoie jamais rien via un canal, donc rien à son sujet n'est simulé : le sandbox rapproche le dépôt de votre carnet d'adresses de portefeuilles et le règle de façon synchrone, exactement comme en production. Il aboutit à un résultat réel plutôt qu'à `AWAITING_COUNTERPARTY` : `ON_HOLD` (aucune correspondance dans le carnet d'adresses), `UNCONFIRMED_OWNERSHIP` (l'entrée correspondante n'a pas de propriété vérifiée), `COUNTERPARTY_MISMATCHED_DATA` (le nom du bénéficiaire ne correspond pas au titulaire du portefeuille), ou `COMPLETED` puis `FINISHED` (correspondance avec une entrée vérifiée).
> Pour recevoir un transfert du Didit Test VASP, utilisez [Déclencher un transfert entrant du Test VASP](https://docs.didit.me/fr/management-api/travel-rule/trigger-test-vasp-inbound.md) avec l'un de vos propres portefeuilles du carnet d'adresses.

### Scénarios du Test VASP pour la Travel Rule

Le `travel_rule.scenarios` du catalogue liste ces scénarios sortants. Indiquez le nom du bénéficiaire ci-dessous dans une transaction `travelRule` sortante, après avoir activé Travel Rule sur votre application sandbox. Les vérifications du seuil et du portefeuille auto-hébergé déclaré décrites ci-dessus s'exécutent en premier.

| Scénario | Nom du bénéficiaire | Résultat |
| - | - | - |
| `accept` | `Didit Test VASP` | `COMPLETED` |
| `decline` | `Didit Test VASP Decline` | `COUNTERPARTY_VASP_GENERAL_DECLINE` |
| `name_mismatch` | `Didit Test VASP Name Mismatch` | `COUNTERPARTY_MISMATCHED_DATA` |
| `not_reachable` | `Didit Test VASP Not Reachable` | `COUNTERPARTY_VASP_NOT_REACHABLE` après de nouvelles tentatives de livraison |
| `timeout` | `Didit Test VASP Timeout` | `EXPIRED` lorsque la vérification d'expiration intervient après la limite d'une minute |
| `self_hosted` | `Didit Test VASP Self Hosted` | `UNCONFIRMED_OWNERSHIP` |

Vous pouvez aussi choisir un scénario avec l'adresse du portefeuille du bénéficiaire au lieu du nom (le portefeuille prime lorsque les deux sont renseignés), et un transfert qui n'indique ni l'un ni l'autre se termine avec `accept`. [Tester Travel Rule en sandbox](https://docs.didit.me/fr/transaction-monitoring/travel-rule-sandbox.md) liste le portefeuille de chaque scénario et son résultat exact.

Le [déclencheur de Test VASP entrant](https://docs.didit.me/fr/management-api/travel-rule/trigger-test-vasp-inbound.md) n'accepte que `accept` et `name_mismatch` dans son champ `scenario`.

> [!NOTE]
>
> **Comment tester une règle avant sa mise en production.** Utilisez
> [Backtest](https://docs.didit.me/fr/transaction-monitoring/rules-api.md#créer-backtester-activer) : il rejoue la règle sur votre historique réel de transactions et renvoie `evaluated` / `matched` / `affected_entities` sans modifier le statut d'une transaction. Associez-le au mode `TEST` sur l'application en production : une règle `TEST` s'évalue sur chaque nouvelle transaction réelle et enregistre les correspondances qu'elle aurait produites, sans modifier le score ni le statut, puis passez au mode `ACTIVE` une fois la sélectivité jugée satisfaisante.

## Comment basculer entre le mode live et le mode sandbox

Live et sandbox sont des **applications distinctes**, afin que le trafic de test et les données de production ne se mélangent jamais. Chaque application possède un `mode` égal à `live` ou `sandbox` :

* Utilisez la clé API d'une application en **mode sandbox** pour obtenir des sessions simulées, non facturées et simulables.
* Utilisez la clé API d'une application en **mode live** pour les vérifications réelles.

Le champ `sandbox_scenario` (lors de la création d'une session et sur l'API AML autonome) ainsi que les endpoints de simulation ne sont acceptés que sur les applications sandbox ; ils sont rejetés sur les applications live.

## Sandbox dans le flux de vérification hébergé

Les sessions créées sous une application sandbox affichent une interface supplémentaire dans le flux de vérification hébergé (l'`url` renvoyée par `POST /v3/session/`) :

* **Bandeau sandbox dans la carte.** Chaque écran affiche un bandeau à l'intérieur de la carte, avec le texte « Données de test uniquement, aucun appel réel », afin qu'il soit toujours évident que la session n'appelle jamais de fournisseurs réels et ne touche jamais à votre solde. Les médias capturés sont stockés comme pour toute session ; utilisez donc les documents d'exemple et les données de test plutôt que de vrais documents d'identité ou des informations personnelles.
* **Sélecteur de scénario préalable au flux.** Avant le début de la capture, un sélecteur intégré à la carte guide l'utilisateur dans le choix d'un résultat de test : il sélectionne d'abord un résultat, puis un déclencheur pour ce résultat. La confirmation appelle `POST /v3/session/{session_id}/sandbox/arm/` (voir [Armer (ou réarmer) la session avant le début du flux](#3-armer-ou-réarmer-la-session-avant-le-démarrage-du-parcours) ci-dessous), puis poursuit le flux avec les valeurs magiques de ce scénario déjà appliquées.
* **Bande de documents d'exemple.** Une rangée de documents d'exemple sandbox (jusqu'à 3) s'affiche juste sous le composant de téléversement et de capture des documents. Appuyez sur l'un d'eux pour l'utiliser à la place d'un téléversement réel.

Les sessions sandbox conservent les médias **réels** capturés : les documents, le selfie, la vidéo de détection du vivant et les justificatifs de domicile sont téléversés et conservés exactement comme pour une session live. Les données *extraites* (champs de vérification d'identité, scores de correspondance faciale, résultats de détection du vivant et autres) ainsi que le résultat de la session lui-même (Approuvé / En cours d'examen / Refusé) sont simulés par le scénario ou la valeur magique, et ne sont jamais déduits des médias capturés. La Business Console marque les sections de données extraites d'une session sandbox avec un badge **Données simulées**, afin que les réviseurs distinguent d'un coup d'œil les parties de la session issues de la capture réelle et celles pilotées par le scénario.

## Scénarios

Chaque scénario est un ensemble nommé de valeurs prédéfinies. Transmettez son slug comme `sandbox_scenario` lors de la création de la session (ou à l'endpoint de simulation) pour reproduire le résultat.

| Slug | Titre | Statut par défaut | Description |
| - | - | - | - |
| `approve` | Parcours idéal : toutes les fonctionnalités approuvent | Approuvé | Comportement par défaut du sandbox : chaque fonctionnalité simulée renvoie son résultat APPROVED sans anomalie. La session se termine avec le statut APPROVED. |
| `decline_aml_hit` | Filtrage AML : personne politiquement exposée | Refusé | Le mock AML renvoie une correspondance et la session est refusée sur la fonctionnalité AML. La correspondance utilise le même [schéma de la correspondance](https://docs.didit.me/fr/core-technology/aml-screening/report-aml-screening.md#champs-par-correspondance) que les fournisseurs AML en production : `url`, `match_score`, `risk_score`, `review_status`, `properties`, `pep_matches[]` et `score_breakdown` sont tous renseignés, et un journal d'avertissement POSSIBLE\_MATCH\_FOUND est écrit. |
| `decline_document_expired` | Vérification d'identité : document expiré | Refusé | Le mock de vérification d'identité renvoie un passeport dont la date d'expiration est passée. La session est refusée lors de la vérification d'identité avec un journal d'avertissement DOCUMENT\_EXPIRED. |
| `decline_minimum_age` | Vérification d'identité : âge inférieur à la limite de la politique | Refusé | Le mock renvoie une date de naissance qui rend l'utilisateur âgé d'environ 10 ans. La vérification de l'âge en production émet MINIMUM\_AGE\_NOT\_MET et le workflow entraîne le refus. |
| `decline_mrz_validation` | Vérification d'identité : échec de la somme de contrôle MRZ | Refusé | Le mock renvoie un passeport dont la somme de contrôle MRZ est corrompue. Le validateur MRZ en production émet MRZ\_VALIDATION\_FAILED et la session est refusée. |
| `decline_could_not_recognize_document` | Vérification d'identité : document illisible | Refusé | Le mock renvoie une réponse vide. En production, COULD\_NOT\_RECOGNIZE\_DOCUMENT est levé et remonté au SDK. |
| `decline_face_match_low_similarity` | Correspondance faciale : similarité inférieure au seuil de refus | Refusé | Le mock de correspondance faciale renvoie un score faible. En production, LOW\_FACE\_MATCH\_SIMILARITY est émis et le mappage des actions du nœud de workflow entraîne le refus. |
| `decline_database_no_match` | Validation en base de données : aucune correspondance sur l'ensemble des services | Refusé | Chaque service de base de données sélectionné renvoie NO\_MATCH. En production, DATABASE\_VALIDATION\_NO\_MATCH est émis et le workflow refuse. |
| `decline_phone_high_risk` | Téléphone : numéro de test à haut risque réservé | Refusé | Le mock de vérification du téléphone bloque la vérification (plage de test réservée). La vérification du téléphone se termine en BLOCKED et émet HIGH\_RISK\_PHONE\_NUMBER. |
| `decline_email_breach` | Vérification de l'e-mail : correspondance dans une base de fuites de données | Refusé | Le mock de la base de données de fuites renvoie une correspondance de fuite sur l'adresse. La vérification de l'e-mail émet BREACHED\_EMAIL\_DETECTED. |
| `decline_ip_blocklist` | Analyse de l'IP : adresse dans la liste de blocage | Refusé | Le mock d'analyse IP refuse la localisation avec IP\_ADDRESS\_IN\_BLOCKLIST. La session est refusée à l'analyse IP. |
| `decline_poa_address_mismatch` | POA : adresse différente de celle fournie | Refusé | Le mock POA refuse le justificatif de domicile avec ADDRESS\_MISMATCH\_WITH\_PROVIDED. La session est refusée au POA. |
| `decline_liveness_attack` | Détection du vivant : attaque par présentation du visage détectée | Refusé | Le mock de détection passive du vivant détecte un signal d'attaque sur le visage et émet LIVENESS\_FACE\_ATTACK. La session est refusée à la détection du vivant. |
| `decline_nfc_chip_not_verified` | Vérification NFC : puce du passeport électronique non vérifiée | Refusé | Le mock du passeport électronique renvoie une puce dont la signature SOD/DG échoue au contrôle d'intégrité. En production, NFC\_CHIP\_NOT\_VERIFIED est émis et la session est refusée à la vérification NFC lorsque le workflow refuse les puces non vérifiées. |
| `decline_nfc_trust_anchor_missing` | Vérification NFC : ancre de confiance de l'émetteur indisponible | Refusé | Le mock renvoie une puce signée par un DSC dont le CSCA émetteur est absent du magasin de confiance. En production, NFC\_TRUST\_ANCHOR\_MISSING est émis et la session est refusée lorsque le workflow refuse les puces non vérifiées. |
| `decline_document_ai_unreadable` | Document AI : document illisible | Refusé | Le mock Document AI ne renvoie aucun champ lisible. En production, DOCUMENT\_AI\_UNREADABLE\_DOCUMENT est émis et le document passe au statut refusé une fois le nombre de tentatives épuisé. |
| `review_aml_possible_match` | Filtrage AML : correspondance possible à examiner | En cours d'examen | Le mock AML renvoie une correspondance à plus faible confiance. La session passe En cours d'examen avec un journal POSSIBLE\_MATCH\_FOUND de niveau avertissement, à résoudre par un analyste. |
| `review_face_match_borderline` | Correspondance faciale : similarité limite | En cours d'examen | Le mock de correspondance faciale renvoie un score compris entre les seuils d'examen et de refus. La session passe à l'état « En cours d'examen » lors de la correspondance faciale. |
| `review_document_borderline_age` | Vérification d'identité : mineur envoyé en examen | En cours d'examen | Le mock renvoie une date de naissance correspondant à un âge inférieur à l'âge minimum configuré dans le workflow. Le minimum\_age\_action du workflow est réglé sur REVIEW au lieu de DECLINE, de sorte que la session passe à l'état « En cours d'examen » lors de la vérification d'identité au lieu d'être refusée. |
| `review_poa_partial_match` | POA : correspondance partielle de l'adresse | En cours d'examen | Le mock POA renvoie une adresse qui ne correspond que partiellement à celle fournie. La session passe à l'état « En cours d'examen » lors de la vérification du justificatif de domicile. |
| `review_database_partial_match` | Validation en base de données : correspondance partielle | En cours d'examen | Les services de base de données renvoient des correspondances partielles sur le nom et la date de naissance. La session passe à l'état « En cours d'examen » lors de la validation en base de données. |
| `decline_kyb_registry_mismatch` | KYB : données du registre incohérentes | Refusé | Le mock du registre renvoie une entreprise dont les données d'immatriculation ne correspondent pas aux détails attendus. La session d'entreprise est refusée lors de la vérification du registre. |
| `review_kyb_registry_partial` | KYB : données du registre partiellement correspondantes | En cours d'examen | Le mock du registre renvoie une entreprise dont le nom ne correspond que partiellement. La session d'entreprise passe à l'état « En cours d'examen » lors de la vérification du registre. |

Les scénarios `review_*` existent pour vous permettre de tester le parcours d'examen manuel (la file d'attente d'examen dans la console, les webhooks `In Review`, les actions d'approbation et de refus du réviseur) sans avoir besoin d'une entrée qui justifie un refus. Les deux scénarios `kyb_*` ci-dessus définissent `expected_details.registration_number` au lieu de `expected_details.first_name` : ils ne s'appliquent qu'aux sessions de vérification d'entreprise (KYB).

## Valeurs magiques

Une valeur magique est une entrée spécifique qui amène une fonctionnalité simulée à émettre un risque donné. Renseignez le champ d'entrée avec la valeur magique (directement ou via un scénario) pour déclencher ce risque.

| Fonctionnalité | Champ d'entrée | Valeur magique | Risque | Description |
| - | - | - | - | - |
| AML | `user_email` | `sandbox+aml_hit@didit.test` | `POSSIBLE_MATCH_FOUND` | AML : personne politiquement exposée ; la simulation AML renvoie une correspondance, et la session est refusée lors du contrôle AML. |
| ID\_VERIFICATION | `expected_details.first_name` | `SANDBOX_OCR_DOCUMENT_EXPIRED` | `DOCUMENT_EXPIRED` | OCR : document expiré ; la session est refusée lors de la vérification d'identité. |
| ID\_VERIFICATION | `expected_details.first_name` | `SANDBOX_OCR_MINIMUM_AGE_NOT_MET` | `MINIMUM_AGE_NOT_MET` | OCR : la date de naissance indique que l'utilisateur n'a pas atteint l'âge minimum configuré ; la session est refusée. |
| ID\_VERIFICATION | `expected_details.first_name` | `SANDBOX_OCR_MAXIMUM_AGE_EXCEEDED` | `MAXIMUM_AGE_EXCEEDED` | OCR : la date de naissance extraite dépasse la politique d'âge maximum configurée. |
| ID\_VERIFICATION | `expected_details.first_name` | `SANDBOX_OCR_DOCUMENT_NUMBER_FORMAT_MISMATCH` | `DOCUMENT_NUMBER_FORMAT_MISMATCH` | OCR : le numéro de document extrait ne correspond pas à l'expression régulière de format attendue pour ce document, issue du registre des documents. |
| ID\_VERIFICATION | `expected_details.first_name` | `SANDBOX_OCR_PERSONAL_NUMBER_FORMAT_MISMATCH` | `PERSONAL_NUMBER_FORMAT_MISMATCH` | OCR : le numéro personnel extrait ne passe pas le contrôle de format du registre des documents. |
| ID\_VERIFICATION | `expected_details.first_name` | `SANDBOX_OCR_DOCUMENT_NOT_SUPPORTED_FOR_APPLICATION` | `DOCUMENT_NOT_SUPPORTED_FOR_APPLICATION` | OCR : le type de document extrait ne fait pas partie de la politique `documents_allowed` de l'application. |
| ID\_VERIFICATION | `expected_details.first_name` | `SANDBOX_OCR_FULL_NAME_MISMATCH_WITH_PROVIDED` | `FULL_NAME_MISMATCH_WITH_PROVIDED` | OCR : le nom figurant sur le document ne correspond pas au nom saisi par le client dans `expected_details` ci-dessus, avec un écart supérieur au seuil de correspondance du nom. |
| ID\_VERIFICATION | `expected_details.first_name` | `SANDBOX_OCR_GENDER_MISMATCH_WITH_PROVIDED` | `GENDER_MISMATCH_WITH_PROVIDED` | OCR : le genre extrait ne correspond pas à `expected_details.gender`. |
| ID\_VERIFICATION | `expected_details.first_name` | `SANDBOX_OCR_DOB_MISMATCH_WITH_PROVIDED` | `DOB_MISMATCH_WITH_PROVIDED` | OCR : la date de naissance extraite ne correspond pas à `expected_details.date_of_birth`. |
| ID\_VERIFICATION | `expected_details.first_name` | `SANDBOX_OCR_COUNTRY_MISMATCH_WITH_PROVIDED` | `COUNTRY_MISMATCH_WITH_PROVIDED` | OCR : le pays de délivrance ne correspond pas à `expected_details.country` (ou `id_country`). |
| ID\_VERIFICATION | `expected_details.first_name` | `SANDBOX_OCR_NATIONALITY_MISMATCH_WITH_PROVIDED` | `NATIONALITY_MISMATCH_WITH_PROVIDED` | OCR : la nationalité extraite ne correspond pas à `expected_details.nationality`. |
| ID\_VERIFICATION | `expected_details.first_name` | `SANDBOX_OCR_IDENTIFICATION_NUMBER_MISMATCH_WITH_PROVIDED` | `IDENTIFICATION_NUMBER_MISMATCH_WITH_PROVIDED` | OCR : le numéro de document, personnel ou fiscal extrait ne correspond pas à `expected_details.identification_number`. |
| ID\_VERIFICATION | `expected_details.first_name` | `SANDBOX_OCR_COULD_NOT_RECOGNIZE_DOCUMENT` | `COULD_NOT_RECOGNIZE_DOCUMENT` | OCR : le pipeline OCR renvoie un résultat vide ou non reconnaissable ; en production, COULD\_NOT\_RECOGNIZE\_DOCUMENT est levé. |
| ID\_VERIFICATION | `expected_details.first_name` | `SANDBOX_OCR_MRZ_NOT_DETECTED` | `MRZ_NOT_DETECTED` | OCR : le document attend une MRZ, mais le pipeline n'a pas pu la localiser. |
| ID\_VERIFICATION | `expected_details.first_name` | `SANDBOX_OCR_MRZ_VALIDATION_FAILED` | `MRZ_VALIDATION_FAILED` | OCR : la MRZ a été trouvée, mais elle échoue à la validation de la somme de contrôle ou du format. |
| ID\_VERIFICATION | `expected_details.first_name` | `SANDBOX_OCR_MRZ_AND_DATA_EXTRACTED_FROM_OCR_NOT_SAME` | `MRZ_AND_DATA_EXTRACTED_FROM_OCR_NOT_SAME` | OCR : les champs d'identité de la MRZ ne correspondent pas aux champs extraits de la zone lisible (VIZ). |
| ID\_VERIFICATION | `expected_details.first_name` | `SANDBOX_OCR_BARCODE_NOT_DETECTED` | `BARCODE_NOT_DETECTED` | OCR : le document attend un code-barres, mais aucun n'a été trouvé. |
| ID\_VERIFICATION | `expected_details.first_name` | `SANDBOX_OCR_BARCODE_VALIDATION_FAILED` | `BARCODE_VALIDATION_FAILED` | OCR : le code-barres a été décodé, mais il échoue à la validation croisée des champs. |
| ID\_VERIFICATION | `expected_details.first_name` | `SANDBOX_OCR_QR_NOT_DETECTED` | `QR_NOT_DETECTED` | OCR : le document attend un QR code, mais aucun n'a été trouvé. |
| ID\_VERIFICATION | `expected_details.first_name` | `SANDBOX_OCR_QR_VALIDATION_FAILED` | `QR_VALIDATION_FAILED` | OCR : le QR code a été décodé, mais il échoue à la validation croisée des champs. |
| ID\_VERIFICATION | `expected_details.first_name` | `SANDBOX_OCR_DATA_INCONSISTENT` | `DATA_INCONSISTENT` | OCR : les contrôles de cohérence interne révèlent des incohérences entre les champs VIZ. |
| ID\_VERIFICATION | `expected_details.first_name` | `SANDBOX_OCR_DOCUMENT_SIDES_MISMATCH` | `DOCUMENT_SIDES_MISMATCH` | OCR : le recto et le verso (document\_name) ne correspondent pas au même document. |
| ID\_VERIFICATION | `expected_details.first_name` | `SANDBOX_OCR_NAME_NOT_DETECTED` | `NAME_NOT_DETECTED` | OCR : ni le prénom ni le nom n'ont pu être extraits du document. |
| ID\_VERIFICATION | `expected_details.first_name` | `SANDBOX_OCR_DATE_OF_BIRTH_NOT_DETECTED` | `DATE_OF_BIRTH_NOT_DETECTED` | OCR : la classe de document attend une date de naissance, mais l'extraction n'en a renvoyé aucune. |
| ID\_VERIFICATION | `expected_details.first_name` | `SANDBOX_OCR_EXPIRATION_DATE_NOT_DETECTED` | `EXPIRATION_DATE_NOT_DETECTED` | OCR : la classe de document attend une date d'expiration, mais l'extraction n'en a renvoyé aucune. |
| ID\_VERIFICATION | `expected_details.first_name` | `SANDBOX_OCR_DOCUMENT_NUMBER_NOT_DETECTED` | `DOCUMENT_NUMBER_NOT_DETECTED` | OCR : ni le numéro de document ni le numéro personnel n'ont pu être extraits. |
| ID\_VERIFICATION | `expected_details.first_name` | `SANDBOX_OCR_COULD_NOT_DETECT_DOCUMENT_TYPE` | `COULD_NOT_DETECT_DOCUMENT_TYPE` | OCR : le classifieur n'a pas pu associer la capture à un type de document pris en charge. |
| ID\_VERIFICATION | `expected_details.first_name` | `SANDBOX_OCR_PORTRAIT_IMAGE_NOT_DETECTED` | `PORTRAIT_IMAGE_NOT_DETECTED` | OCR : le pipeline n'a pas pu isoler de zone de portrait sur le document. |
| ID\_VERIFICATION | `expected_details.first_name` | `SANDBOX_OCR_UNPARSED_ADDRESS` | `UNPARSED_ADDRESS` | OCR : le document comporte un champ d'adresse, mais le géocodage ou l'analyse n'a renvoyé aucun résultat exploitable. |
| DATABASE\_VALIDATION | `expected_details.first_name` | `SANDBOX_DB_NO_MATCH` | `DATABASE_VALIDATION_NO_MATCH` | Validation en base de données : tous les services gouvernementaux et de registres renvoient NO\_MATCH ; la session est refusée sur la validation en base de données. |
| FACEMATCH | `expected_details.first_name` | `SANDBOX_FACE_LOW_MATCH` | `LOW_FACE_MATCH_SIMILARITY` | Correspondance faciale : le score de similarité est inférieur au seuil de refus ; la session est refusée sur la correspondance faciale. |
| PHONE | `phone_number` | `+15005550009` | `HIGH_RISK_PHONE_NUMBER` | Téléphone : numéro de test réservé, non livrable ou à haut risque ; la simulation de vérification du téléphone renvoie un échec. |
| EMAIL | `user_email` | `sandbox+breach@didit.test` | `BREACHED_EMAIL_DETECTED` | E-mail : la base de données de fuites renvoie une correspondance pour cette adresse. |
| LOCATION | `expected_details.first_name` | `SANDBOX_IP_BLOCKLIST` | `IP_ADDRESS_IN_BLOCKLIST` | Analyse IP : l'adresse IP de l'appelant figure dans la liste de blocage de l'application ; la session est refusée sur l'analyse IP. |
| PROOF\_OF\_ADDRESS | `expected_details.first_name` | `SANDBOX_POA_ADDRESS_MISMATCH` | `ADDRESS_MISMATCH_WITH_PROVIDED` | Justificatif de domicile : l'adresse figurant sur le document téléversé ne correspond pas à l'adresse pré-remplie par le client dans `expected_details` ; la session est refusée sur le justificatif de domicile. |
| LIVENESS | `expected_details.first_name` | `SANDBOX_LIVENESS_ATTACK` | `LIVENESS_FACE_ATTACK` | Détection du vivant : le contrôle passif simulé détecte un signal d'attaque par présentation ; la session est refusée sur la détection du vivant. |
| NFC | `expected_details.first_name` | `SANDBOX_NFC_CHIP_NOT_VERIFIED` | `NFC_CHIP_NOT_VERIFIED` | NFC : la simulation de passeport électronique renvoie une puce dont la signature SOD/DG échoue à la vérification d'intégrité ; en production, NFC\_CHIP\_NOT\_VERIFIED est émis et la session est refusée lorsque le workflow refuse les puces non vérifiées. |
| NFC | `expected_details.first_name` | `SANDBOX_NFC_TRUST_ANCHOR_MISSING` | `NFC_TRUST_ANCHOR_MISSING` | NFC : le DSC se rattache à une CSCA absente du magasin de confiance ; en production, NFC\_TRUST\_ANCHOR\_MISSING est émis et l'action configurée pour les puces non vérifiées est appliquée. |
| DOCUMENT\_AI | `expected_details.first_name` | `SANDBOX_DOCUMENT_AI_UNREADABLE` | `DOCUMENT_AI_UNREADABLE_DOCUMENT` | Document AI : l'extraction ne renvoie aucun champ lisible ; en production, DOCUMENT\_AI\_UNREADABLE\_DOCUMENT est émis et le document passe au statut refusé une fois le nombre de tentatives épuisé. |
| AML | `user_email` | `sandbox+aml_review@didit.test` | `POSSIBLE_MATCH_FOUND` | AML : correspondance possible qui doit être traitée manuellement ; la session passe en cours d'examen. |
| FACEMATCH | `expected_details.first_name` | `SANDBOX_FACE_BORDERLINE_MATCH` | `LOW_FACE_MATCH_SIMILARITY` | Correspondance faciale : similarité limite entre les seuils d'examen et de refus ; la session passe en cours d'examen. |
| ID\_VERIFICATION | `expected_details.first_name` | `SANDBOX_OCR_BORDERLINE_AGE` | `MINIMUM_AGE_NOT_MET` | OCR : la date de naissance est inférieure à l'âge minimum, mais le workflow soumet à examen plutôt que de refuser les échecs liés à l'âge minimum ; la session passe en cours d'examen. |
| DATABASE\_VALIDATION | `expected_details.first_name` | `SANDBOX_DB_PARTIAL_MATCH` | `DATABASE_VALIDATION_PARTIAL_MATCH` | Validation en base de données : l'identification correspond, mais le nom et la date de naissance ne correspondent que partiellement ; la session passe en cours d'examen. |
| PROOF\_OF\_ADDRESS | `expected_details.first_name` | `SANDBOX_POA_PARTIAL_MATCH` | `ADDRESS_MISMATCH_WITH_PROVIDED` | Justificatif de domicile : l'adresse figurant sur le document téléversé correspond partiellement à l'adresse fournie ; la session passe en cours d'examen. |
| KYB\_REGISTRY | `expected_details.registration_number` | `SANDBOX-KYB-MISMATCH` | `KYB_REGISTRY_DATA_MISMATCH_WITH_EXPECTED` | KYB : les données de l'entreprise dans le registre ne correspondent pas aux informations attendues ; la session est refusée. |
| KYB\_REGISTRY | `expected_details.registration_number` | `SANDBOX-KYB-REVIEW` | `KYB_REGISTRY_DATA_PARTIAL_MATCH_WITH_EXPECTED` | KYB : les données de l'entreprise dans le registre correspondent partiellement ; la session passe en cours d'examen. |

## Consultation sans document et portefeuilles d'identité

Les applications sandbox peuvent activer tous les portefeuilles d'identité du catalogue par pays, y compris ceux qui ne sont pas disponibles sur les applications en production.
Le scénario par défaut `approve` simule une identité vérifiée sans connexion à un portefeuille externe.
Le résultat est enregistré dans la session et suit l'étape suivante normale du workflow.
Le sandbox ne valide aucun justificatif de portefeuille réel et ne facture pas les tentatives simulées.

Les requêtes de consultation valident toujours les champs saisis et appliquent la limite de tentatives configurée, qui est fixée à une tentative par défaut.
Utilisez les scénarios suivants pour tester les nouvelles tentatives et les règles de repli :

| Scénario | Résultat simulé |
| - | - |
| `lookup_partial_match` | Correspondance partielle dans le registre ; compte dans la limite de tentatives. |
| `lookup_no_match` | Le registre répond sans correspondance ; compte dans la limite de tentatives. |
| `lookup_provider_error` | Le registre ne répond pas ; l'utilisateur est invité à réessayer, et après trois tentatives sans réponse, la règle de repli en cas d'erreur du fournisseur s'applique. |
| `wallet_cancelled` | L'utilisateur annule la connexion au portefeuille. |
| `wallet_timeout` | La connexion au portefeuille expire. |
| `wallet_provider_error` | Le portefeuille ne peut pas terminer la connexion. |

Les échecs liés au portefeuille suivent le paramètre du pays : repli vers la capture du document ou refus.
Les tentatives de consultation terminées sont enregistrées séparément : deux tentatives autorisées produisent donc deux résultats avant le repli.
Toute l'utilisation du sandbox reste gratuite.

## Contrôle de compte de la vérification bancaire

Une étape de vérification bancaire en sandbox propose [les deux méthodes](https://docs.didit.me/fr/core-technology/bank-verification/verification-methods.md) dans chaque pays, dans l'ordre défini par l'étape, sur un service simulé sans banque et sans frais.
Avec l'ordre par défaut, la personne commence par la connexion bancaire et choisit **Saisissez les coordonnées de votre compte** pour lancer le [contrôle de compte](https://docs.didit.me/fr/core-technology/bank-verification/account-check.md) ; définissez `bank_method_order` sur `["account_lookup", "open_banking"]` pour commencer directement par celui-ci.
Les quatre derniers caractères du numéro de compte saisi déterminent la réponse ; voir [Tester dans le sandbox](https://docs.didit.me/fr/core-technology/bank-verification/account-check.md#tester-dans-la-sandbox) pour chaque terminaison et un compte valide par format.
L'[API de contrôle de compte](https://docs.didit.me/fr/standalone-apis/bank-account-check.md) renvoie une clé sandbox à partir des mêmes terminaisons.

## Les documents d'exemple

> [!WARNING]
>
> Ne téléversez jamais de vrais documents d'identité en sandbox. Utilisez plutôt les documents d'exemple intégrés.

Le flux hébergé propose trois documents d'exemple, un par type de document :

| Pays | Type de document |
| - | - |
| Espagne | Carte nationale d'identité |
| Argentine | Passeport |
| Pologne | Permis de conduire |

Sélectionnez un exemple dans la bande pour l'utiliser à la place d'une capture réelle. Les données extraites et le résultat de la session proviennent toujours du scénario ou de la valeur magique sélectionnés ; n'importe quel exemple fonctionne donc avec n'importe quel scénario.

## Identité d'exemple et test de `expected_details`

Chaque document sandbox est fabriqué à partir d'une seule identité **fixe**.
Les valeurs extraites sont identiques d'une session à l'autre et ne sont jamais calculées à partir de la date du jour. Vous pouvez donc pré-remplir `expected_details` avec ces valeurs et vérifier de bout en bout la comparaison des champs et la gestion des avertissements. Transmettez les valeurs ci-dessous et les contrôles de comparaison passent ; transmettez autre chose et l'avertissement `*_MISMATCH_WITH_PROVIDED` correspondant se déclenche volontairement.

Les dates sont communes à tous les documents d'exemple :

| Champ | Valeur |
| - | - |
| `date_of_birth` | `1990-06-15` |
| Date de délivrance | `2025-06-15` |
| Date d'expiration | `2035-06-15` |

Le reste de l'identité dépend du document utilisé :

| `sandbox_sample` | Document | `first_name` | `last_name` | `gender` | `nationality` | `id_country` | `identification_number` |
| - | - | - | - | - | - | - | - |
| *(par défaut, aucun échantillon sélectionné)* | passeport électronique brésilien | `GUSTAVO` | `MATSUMOTO` | `M` | `BRA` | `BRA` | `YC531181` |
| `spain-id-card-2021` | Carte nationale d'identité espagnole | `CARMEN` | `ESPAÑOLA ESPAÑOLA` | `F` | `ESP` | `ESP` | `CAA000000` |
| `argentina-passport-2009` | Passeport argentin | `MARIA VICTORIA` | `VILLAREAL` | `F` | `ARG` | `ARG` | `AAF794880` |
| `poland-driving-license-2019` | Permis de conduire polonais | `JAN` | `KOWALSKI` | absent de ce document | `POL` | `POL` | `SP005/89/5` |

```json theme={null}
{
  "workflow_id": "<your-workflow-uuid>",
  "expected_details": {
    "date_of_birth": "1990-06-15",
    "gender": "M",
    "nationality": "BRA",
    "identification_number": "YC531181"
  }
}
```

`first_name` et `last_name` font exception : le sandbox reprend sur le document fabriqué les noms que vous transmettez dans `expected_details`, de sorte que la comparaison des noms réussit quel que soit le nom envoyé.
Utilisez la valeur magique `SANDBOX_OCR_FULL_NAME_MISMATCH_WITH_PROVIDED` pour simuler une non-concordance de nom, et `SANDBOX_OCR_DOB_MISMATCH_WITH_PROVIDED` pour une non-concordance de date de naissance.

> [!NOTE]
>
> Si votre workflow restreint `documents_allowed` à un pays ou à un type de document qui exclut le passeport électronique brésilien, le sandbox fabrique à la place un document à partir du premier pays autorisé. Ainsi, `nationality`, `id_country` et le nom du document suivent ce pays. Les dates ci-dessus restent les mêmes.

### Ce que le document fabriqué ne contient pas

Le document fabriqué est le modèle générique du pays et du type de document autorisés. Les champs que seul un document réel délivré par un État fournit restent donc vides. L'élément qui importe pour le routage est la **région / l'État américain** (`kyc.region`) : un permis de conduire américain ou une carte d'identité américaine fabriqués en sandbox n'a pas d'État. Une condition de branche telle que `Region equals IL` ne peut donc jamais correspondre en sandbox. Si aucune autre branche du nœud ne correspond non plus, le flux emprunte la branche de repli (celle sans condition). Ce n'est pas un examen ni un échec de la branche : la condition n'a simplement rien à lire. Un champ absent fait aussi échouer `not equals` et `not in`. Voir [comment les conditions de branche lisent les données de session](https://docs.didit.me/fr/console/workflows.md#comment-les-conditions-de-branchement-lisent-les-données-de-session) pour la différence entre un champ absent et une chaîne vide.

Pour tester un flux qui dépend de l'État en sandbox, pilotez la décision à partir d'une valeur que vous contrôlez sur la session plutôt qu'à partir du document :

* Envoyez l'État dans `metadata` lors de la création de la session (par exemple `"metadata": {"credential_state": "IL"}`) et branchez sur `metadata.credential_state`. Les métadonnées sont évaluées en sandbox exactement comme en production.
* Conservez la condition `kyc.region`, dérivée du document, pour le trafic réel si vous avez aussi besoin que le document prouve l'État. En production, la région est lue sur le document réel.

Le reste du routage est identique au mode production : le graphe du workflow, les conditions de branche, les valeurs de `metadata` et de `expected_details`, les nœuds d'action et les nœuds de statut fonctionnent tous réellement. Le sandbox ne force jamais une session en examen de lui-même : une session en sandbox passe **En cours d'examen** uniquement lorsque le workflow l'y achemine (un scénario `review_*`, une valeur magique associée à une action d'examen, ou un nœud de statut dans le graphe).

## Codes OTP et consentement à recevoir des e-mails

* **OTP téléphone :** la vérification du téléphone du sandbox accepte n'importe quel code bien formé (4 à 8 chiffres ; `123456` inclus). Une saisie mal formée renvoie toujours `400`.
* **OTP e-mail :** la vérification de l'e-mail du sandbox accepte n'importe quel code bien formé (`123456` inclus). Une saisie mal formée renvoie toujours `400`.

Par défaut, les sessions sandbox n'envoient **pas** d'e-mails (alertes d'examen, changements de statut, OTP, nouvelle soumission, nouveau lien de session, etc.). Pour envoyer malgré tout un e-mail, utilisez l'un de ces motifs d'opt-in sur l'adresse du destinataire :

| Motif d'opt-in | Exemple |
| - | - |
| `<local>+sandbox@<domain>` | `alice+sandbox@example.com` |
| `*@didit.test` | `alice@didit.test` |

## Pilotage des résultats : scénarios, valeurs magiques, armement et endpoint de simulation

Il existe cinq façons de contrôler le résultat d'un sandbox.

### 1. `sandbox_scenario` à la création de la session

Renseignez le slug du scénario lors de la création de la session (`POST /v3/session/`). Le flux de création insère les valeurs magiques regroupées dans le scénario dans les champs de saisie de la session, afin que les fournisseurs simulés produisent le résultat voulu via le pipeline de workflow réel.

```json theme={null}
{
  "workflow_id": "<your-workflow-uuid>",
  "sandbox_scenario": "decline_document_expired"
}
```

### 2. Valeurs magiques saisies à la main

Renseignez vous-même les champs de saisie (par exemple `expected_details.first_name = "SANDBOX_OCR_DOCUMENT_EXPIRED"`, ou `user_email = "sandbox+aml_hit@didit.test"`). Consultez le tableau des valeurs magiques ci-dessus pour le registre complet.

### 3. Armer (ou réarmer) la session avant le démarrage du parcours

Définissez ou remplacez le scénario armé sur une session existante, tant qu'elle n'a pas dépassé le statut `Not Started`. C'est l'endpoint appelé par le [sélecteur de scénario avant le parcours](#sandbox-dans-le-flux-de-vérification-hébergé). Vous pouvez également l'appeler vous-même pour créer un sélecteur personnalisé ou un banc de test :

```
POST /v3/session/{session_id}/sandbox/arm/
Session-Token: <session_token>
```

```json theme={null}
{
  "scenario": "decline_document_expired"
}
```

Réponse 200 :

```json theme={null}
{
  "session_id": "<session_id>",
  "scenario": "decline_document_expired",
  "status": "Not Started"
}
```

* Authentifiez-vous avec le `Session-Token` propre à la session (renvoyé sous forme de `session_token` lors de la création de la session), et non avec votre clé API applicative : il s'agit d'un endpoint destiné au client.
* Renvoie `400` pour un slug de scénario inconnu, et `400` lorsque la session a dépassé le statut `Not Started` (`"Scenario can only be armed before the verification starts."`).
* Renvoie `404` lorsque le `Session-Token` appartient à une application de production (hors sandbox), ou ne correspond pas au `session_id` du chemin.
* **Réarmer remplace le scénario précédent.** Seules les valeurs magiques écrites par le scénario précédent sont effacées ; les informations saisies à la main par l'utilisateur (e-mail, prénom, etc.) restent intactes. Par exemple : armez `decline_phone_high_risk`, puis armez `approve` : le numéro de téléphone redevient non renseigné, mais un e-mail saisi par le client survit aux deux appels.

### 4. L'endpoint de simulation

Forcez un statut final après coup :

* Console / clé API (nécessite l'autorisation `write:sessions` ; une clé API à portée restreinte doit avoir un accès en écriture aux sessions) : `POST /v3/session/{session_id}/simulate/`
* Flux hébergé (en-tête `Session-Token`) : `POST /v3/session/{session_id}/sandbox/simulate/`

Les deux fonctionnent sur les sessions sandbox KYC et KYB.
Une session en production (hors sandbox) renvoie `404`, de même qu'un `Session-Token` qui ne correspond pas au `session_id` du chemin.

Tous les champs du corps sont facultatifs, mais au moins l'un de `new_status`, `scenario` ou `risk` est requis :

| Champ | Type | Rôle |
| - | - | - |
| `new_status` | chaîne | `Approved`, `Declined`, `In Review`, `Expired` ou `Abandoned`. Si vous l'omettez, la valeur par défaut est le statut par défaut du dossier de risque (`risk`, ou le premier risque porté par les valeurs magiques du scénario), sinon le statut par défaut du scénario. |
| `scenario` | chaîne, 100 caractères maximum | Un slug de scénario. Sans `risk`, le premier risque porté par ses valeurs magiques est appliqué. |
| `risk` | chaîne, 128 caractères maximum | Un dossier de risque. Son avertissement est ajouté à la session. |
| `node_id` | chaîne, 128 caractères maximum | Le nœud du workflow auquel l'avertissement est rattaché. Par défaut, le nœud actuel de la session. |
| `comment` | chaîne, 500 caractères maximum | Note ajoutée à l'entrée d'activité enregistrée lors du changement de statut. |
| `send_webhooks` | booléen, par défaut `true` | Indique si le changement de statut envoie des webhooks. |

`send_webhooks: true` envoie exactement les webhooks qu'envoie un vrai changement de statut : `status.updated`, ainsi que les événements `user.status.updated` et `user.data.updated` (ou `business.status.updated` et `business.data.updated` pour une session d'entreprise) que ce changement déclenche, vers les destinations qui y sont abonnées.
Avec `send_webhooks: false`, le statut change quand même, mais aucun webhook n'est journalisé ni envoyé.
La récupération des webhooks manqués ne renvoie jamais cette décision, et la console se met tout de même à jour en direct.
Le changement de statut suivant de la session envoie les webhooks normalement.

```json theme={null}
{
  "scenario": "decline_aml_hit",
  "send_webhooks": false
}
```

Réponse 200 :

```json theme={null}
{
  "session_id": "<session_id>",
  "previous_status": "In Progress",
  "status": "Declined",
  "scenario": "decline_aml_hit",
  "risk": "POSSIBLE_MATCH_FOUND",
  "send_webhooks": false
}
```

* `status` est le statut défini par la simulation, et `previous_status` celui que la session avait auparavant.
* `scenario` reprend votre slug et `risk` est le dossier de risque appliqué ; chacun vaut `null` lorsqu'il n'y en a pas.
* `send_webhooks` reprend la valeur appliquée.
* Renvoie `400` pour un scénario ou un risque inconnu, lorsqu'aucun `new_status` ne peut être déduit, pour tout autre `new_status`, et lorsque la session possède déjà le statut demandé (`["The new status is the same as the current status."]`).

### 5. `sandbox_scenario` sur l'API AML autonome

Le filtrage AML côté back-end n'a pas d'utilisateur final ni de session à armer : le slug doit donc figurer directement dans la requête de filtrage (`POST /v3/aml/`) :

```json theme={null}
{
  "full_name": "Ada Lovelace",
  "save_api_request": true,
  "sandbox_scenario": "decline_aml_hit"
}
```

* `decline_aml_hit` renvoie une correspondance au format de production et clôt le filtrage avec le statut `Declined` ; `review_aml_possible_match` le clôt avec le statut `In Review`. Un scénario qui n'arme aucun résultat AML laisse le filtrage sans alerte.
* Avec `save_api_request: true` (valeur par défaut), le filtrage est enregistré exactement comme avec une clé de production, de sorte que le `request_id` renvoyé se résout via `GET /v3/session/{request_id}/decision/` et `GET /v3/session/{request_id}/generate-pdf/`.
* Renvoie `400` pour un slug de scénario inconnu, et `400` lorsque la clé API appartient à une application de production.

## Où apparaît `sandbox_scenario`

Le slug du scénario armé (`null` si aucun n'est armé) est renvoyé sur certaines surfaces et volontairement omis sur d'autres :

| Surface | Exposé ? |
| - | - |
| Payload de l'étape en cours (KYC et KYB) | Oui, sous la forme de `sandbox_scenario` |
| `GET /v1/session/{id}/decision/` | Oui, sous la forme de `sandbox_scenario` |
| `GET /v3/session/{id}/decision/` (voir [Récupérer la session](https://docs.didit.me/fr/sessions-api/retrieve-session.md)) | Oui, `sandbox_scenario` au premier niveau (null si aucun scénario n'est armé) |
| Webhooks de session (`status.updated`, `data.updated`) | Oui, sous la forme de `sandbox_scenario`, `null` pour les sessions de production ou les sessions sandbox sans scénario armé |

Si votre intégration doit se baser sur le scénario armé côté serveur, lisez-le dans l'enveloppe du webhook ou dans l'un des deux endpoints de décision (`v1` ou `v3`).

## Utilisation et facturation

L'utilisation du sandbox est suivie, mais jamais facturée :

* Chaque appel simulé enregistre tout de même un événement d'utilisation (`is_sandbox: true`, au tarif de `0.0000`) afin que le volume du sandbox reste visible pour le débogage. Cet événement n'est cependant jamais ajouté à vos totaux d'utilisation, n'est jamais déduit de votre solde et n'apparaît jamais sur une facture.
* Les éléments de la Business Console consacrés au solde, à la recharge et à l'utilisation en production excluent par défaut l'utilisation du sandbox. Les endpoints de consultation de l'utilisation liée à la recharge acceptent un paramètre `environment` (`live`, valeur par défaut, ou `sandbox`) afin d'examiner séparément le volume du sandbox, toujours à coût nul et sans consommer l'offre gratuite.
* La Vérification de l'e-mail et la Vérification du téléphone sont facturées par requête et non par résultat de session, et le sandbox ne peut pas reproduire entièrement ce mode de facturation au niveau des webhooks. Les contrôles e-mail et téléphone en sandbox enregistrent tout de même un événement d'utilisation par requête au tarif de `0.0000`, comme toutes les autres fonctionnalités simulées. Il s'agit d'un écart connu et accepté avec le comportement de facturation en production, et non d'un bogue.
* La structure de réponse de la Validation en base de données dans le sandbox diffère volontairement de la structure propre à chaque fournisseur en production, puisqu'il n'existe aucun fournisseur réel à imiter. Considérez les payloads de Validation en base de données du sandbox comme un substitut du résultat (statut et code d'avertissement), et non comme un aperçu octet pour octet de la réponse d'un fournisseur réel.


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