Testing Travel Rule in Sandbox
The sandbox environment lets you exercise every Travel Rule behavior your integration will meet in production — paused crypto payouts, held crypto deposits, and self-hosted wallet ownership proofs — without any real counterparty institution being involved.
Your side of the flow is identical to production: you look VASPs up in the real directory, create recipients and payouts with the same requests, and receive the same webhooks. What sandbox changes is the counterparty side: no real VASP ever receives or answers a Travel Rule message from sandbox, so you simulate the counterparty's decision yourself with a single sandbox endpoint.
Travel Rule behavior appears in your sandbox account once Caliza enables it for you. If payouts never pause and deposits are never held, contact Caliza support to have it enabled.
The clearance endpoint
Whenever a transaction is waiting on a Travel Rule decision — a payout pausing for the counterparty VASP's authorization, or a deposit held for the inbound message's verdict — resolve it with:
Endpoint: POST /v1/transactions/sandbox/travel-rule-clearance
curl -X POST "https://api.sandbox.caliza.com/core-api/v1/transactions/sandbox/travel-rule-clearance" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer {{ACCESS_TOKEN}}" \
-d '{
"transactionId": "{{TRANSACTION_ID}}",
"outcome": "AUTHORIZED"
}'| Field | Type | Required | Description |
|---|---|---|---|
transactionId | string | Yes | The transaction waiting on Travel Rule clearance |
outcome | string | Yes | AUTHORIZED or REJECTED — the decision the counterparty would have made |
The effect mirrors production exactly:
- Payout +
AUTHORIZED— the withdrawal resumes and completes as usual. - Payout +
REJECTED— the payout stays paused under compliance review (in production this is a manual-review case handled by Caliza). - Deposit +
AUTHORIZED— the held deposit is credited andPAYMENT_IN_COMPLETEDfires. - Deposit +
REJECTED— the deposit stays held for manual compliance review.
| HTTP | Code | When |
|---|---|---|
| 404 | travel-rule.transfer_not_found | The transaction has no Travel Rule to resolve — it was created before Travel Rule was enabled, or is not a crypto flow |
| 422 | travel-rule.clearance_not_applicable | The transaction's Travel Rule was already resolved |
Testing crypto payouts
- Create a crypto recipient with a
vaspIdfrom the VASP directory — any real provider works; sandbox never contacts it. - Create the payout (
POST /v1/transactions). It proceeds normally until the withdrawal step, then pauses — the transaction keeps its current status (for examplePROCESSING), exactly as documented for production. - Simulate the counterparty's decision with the clearance endpoint.
AUTHORIZEDlets the payout complete;REJECTEDleaves it under review.
A payout stays paused indefinitely until you call the clearance endpoint — there is no automatic timeout on the outbound side.
Testing crypto deposits
Simulate deposits with the mock stablecoin deposit endpoint. Two optional fields control the Travel Rule scenario:
fromAddress— the on-chain origin of the deposit (random when omitted).travelRule— when present withwithMessage: true, the sender's VASP transmits a Travel Rule message for the deposit (simulated); omit it (or setwithMessage: false) to simulate a deposit from a self-hosted wallet, for which no message ever arrives.
curl -X POST "https://api.sandbox.caliza.com/core-api/v1/transactions/sandbox/crypto-deposit" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer {{ACCESS_TOKEN}}" \
-d '{
"beneficiaryId": "{{BENEFICIARY_ID}}",
"walletAddress": "{{WALLET_ADDRESS}}",
"amount": 1500.0,
"network": "ETH",
"currency": "USDC",
"travelRule": { "withMessage": true }
}'The sandbox holds third-party deposits at or above 1,000 USDC/USDT; smaller deposits are credited immediately. The scenarios:
| Scenario | Request | What happens |
|---|---|---|
| Deposit below the threshold | any, amount < 1000 | Credited immediately, no hold |
| VASP deposit, message arrives | travelRule.withMessage: true | Deposit held → resolve with the clearance endpoint → credited (PAYMENT_IN_COMPLETED) or kept under review |
| VASP deposit, name mismatch | travelRule: { "withMessage": true, "beneficiaryName": "Some Other Name" } | The declared recipient name fails the beneficiary name check → deposit stays held for compliance review (the clearance endpoint can still resolve it) |
| Self-hosted origin, no message | travelRule omitted or withMessage: false | Deposit held → after the sandbox waiting period (30 minutes) the origin address is screened and the deposit is credited automatically |
travelRule.beneficiaryName is the recipient name the sending VASP declares in the message — it defaults to the account's registered name, which passes the name check. originatorName (the declared sender) can also be set; it defaults to a test value.
Deposits with a Travel Rule message require the destination wallet to be registered for Travel Rule. Wallets created after Travel Rule was enabled on your account register automatically; for wallets created before that, ask Caliza support to register them — otherwise the simulated message is not linked to the deposit and the timeout path applies instead.
Testing self-hosted wallet proofs
Both ownership proof methods work end to end in sandbox:
- Signature proof — identical to production: issue the delegate token, collect the
eip-191/tip-191signature (SafeConnect, or manually via the attestation endpoint), submit it. Verification is real. - Microtransfer (Satoshi test) — start the test, then deliver the expected on-chain transfer with the mock deposit endpoint, using
fromAddressto send it from the wallet being proven:
curl -X POST "https://api.sandbox.caliza.com/core-api/v1/transactions/sandbox/crypto-deposit" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer {{ACCESS_TOKEN}}" \
-d '{
"beneficiaryId": "{{BENEFICIARY_ID}}",
"walletAddress": "{{destinationAddress from the microtransfer test}}",
"amount": {{expectedAmount from the microtransfer test}},
"network": "ETH",
"currency": "{{expectedCurrency from the microtransfer test}}",
"fromAddress": "{{the wallet address being proven}}"
}'The amount, currency, destination and origin must match the pending test exactly; the proof then flips to VERIFIED automatically, and payouts to the recipient become possible.
To test the travel-rule.ownership_proof_required error, simply create a simulation or transaction targeting a self-hosted recipient before collecting a proof.
When testing payouts to self-hosted wallets, use an external wallet address as the destination — not one of your own Caliza deposit addresses. A payout addressed to your own custody is not a real withdrawal and does not clear the Travel Rule the same way.
Related Articles
Updated 22 days ago
