Before you start
- Use a sandbox application’s API key. Live applications never reach the test VASP.
- Turn Travel Rule on with a legal name:
- Optionally subscribe a webhook destination to
travel_rule.status.updated. Sandbox delivers it, marked"environment": "sandbox".
The Didit Test VASP
GET /v1/sandbox/scenarios/ returns the test VASP’s profile and every scenario in its travel_rule object, so your tests can read the trigger values instead of hard-coding them:
Every value is test data. The test VASP is not a member of any Travel Rule network, and no result in sandbox shows that a real counterparty or network can be reached.
Outbound scenarios
Every outboundtravelRule transaction of a sandbox application that needs an exchange goes to the test VASP. Pick the outcome with the beneficiary wallet address (case does not matter), or with a beneficiary name of the form Didit Test VASP <suffix>; the wallet wins when both are set. With neither, or with a suffix the table does not list, the transfer completes (accept).
A transfer that needs no exchange never reaches the test VASP: one below your threshold_amount, one to your user’s own verified wallet, and one whose counterparty wallet you declared self-hosted. A counterparty VASP you or your end user picked by hand from the directory is judged by the routes a live application would have: when its entry has one (a verified TRP endpoint, a network your application sends on, or a compliance contact), the transfer goes to the test VASP; when it has none, the transfer ends COUNTERPARTY_VASP_NOT_FOUND, as it would on a live application.
rail is TEST_VASP, and the transfers list names Didit Test VASP as its beneficiary VASP. Follow it in the travel_rule.status.updated webhooks, or read GET /v3/transactions/{transaction_id}/.
name_mismatchcompares the beneficiary name you sent with the holder name the test VASP answers with, at your name rule for the beneficiary’s entity type (matching_rules.individual.nameormatching_rules.company.name, which followname_matching_strictnessuntil you set them). The transfer and the timeline entry that decided it carryname_match(withcompared_with: "counterparty_vasp") anddata_matchwithmismatched_fields: ["name"].not_reachablekeeps the transferAWAITING_COUNTERPARTYwhile it retries, withdelivery.statusRETRYINGandlast_errortest VASP is not answering, then makes itCOUNTERPARTY_VASP_NOT_REACHABLE. Send{"action": "resend"}afterwards to run it again.self_hostedhas the test VASP answer that the wallet is self-hosted. Record the proof with the wallet ownership widget (minted for you whileauto_wallet_verificationis on) orPOST .../travel-rule/ownership/with{"confirmed": true}: the wallet is added to your address book under the beneficiary’s name and the name match decides the transfer. A match completes it and marks the wallet verified;{"confirmed": false}declines it.
Inbound transfers from the test VASP
To test the receiving side, have the test VASP send you a transfer withPOST /v3/travel-rule/test-vasp/inbound/. Name one of your application’s own address-book wallets: the transfer is decided by the same inbound path as a real one, against your address book, your ownership mode and your name rules.
The
201 response carries transaction_id, txn_id, scenario, travel_rule_status, detail, test_vasp: true and the travel_rule transfer. A live application gets 400 ("The Didit Test VASP is only available on sandbox applications."), another scenario gets 400, and an application with Travel Rule off gets 409.
Decide a transfer that waits with
POST .../travel-rule/ownership/, as you would a real one: {"confirmed": true} completes it and {"confirmed": false} declines it.
A deposit you report yourself with POST /v3/transactions/ is not one the test VASP sent: it stays AWAITING_COUNTERPARTY waiting for its originating VASP, and its timeline names the endpoint above. It fires no webhook until it expires after confirmation_timeout_hours. POST /v3/travel-rule/inbound/ still settles an after-deposit registration against your address book, as on a live application.
Webhooks in sandbox
travel_rule.status.updated fires for sandbox applications on every status change, with "environment": "sandbox". A transfer the test VASP answered also carries rail: "TEST_VASP", test_vasp: true and test_vasp_scenario. The rest of sandbox still behaves as described in Transaction Monitoring in sandbox: rules are not evaluated, transaction.created and transaction.status.updated are not sent, and nothing is billed.
What sandbox does not prove
- That a real counterparty, a network membership or Didit’s public TRP host works. None of them is contacted.
- That your network credentials are valid. A connected membership is proven by its first live exchange.
- The directory routes of real VASPs: on a sandbox application every route reads
unavailablewithreason: sandbox_application, and every rowreachable: false.