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"
  }'
FieldTypeRequiredDescription
transactionIdstringYesThe transaction waiting on Travel Rule clearance
outcomestringYesAUTHORIZED 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 and PAYMENT_IN_COMPLETED fires.
  • Deposit + REJECTED — the deposit stays held for manual compliance review.
HTTPCodeWhen
404travel-rule.transfer_not_foundThe transaction has no Travel Rule to resolve — it was created before Travel Rule was enabled, or is not a crypto flow
422travel-rule.clearance_not_applicableThe transaction's Travel Rule was already resolved

Testing crypto payouts

  1. Create a crypto recipient with a vaspId from the VASP directory — any real provider works; sandbox never contacts it.
  2. Create the payout (POST /v1/transactions). It proceeds normally until the withdrawal step, then pauses — the transaction keeps its current status (for example PROCESSING), exactly as documented for production.
  3. Simulate the counterparty's decision with the clearance endpoint. AUTHORIZED lets the payout complete; REJECTED leaves 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 with withMessage: true, the sender's VASP transmits a Travel Rule message for the deposit (simulated); omit it (or set withMessage: 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:

ScenarioRequestWhat happens
Deposit below the thresholdany, amount < 1000Credited immediately, no hold
VASP deposit, message arrivestravelRule.withMessage: trueDeposit held → resolve with the clearance endpoint → credited (PAYMENT_IN_COMPLETED) or kept under review
VASP deposit, name mismatchtravelRule: { "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 messagetravelRule omitted or withMessage: falseDeposit 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-191 signature (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 fromAddress to 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


Did this page help you?