Skip to main content

Sandbox integration

The Sandbox is an isolated Environment where Deposits, Withdrawals, and Ledger run the exact same code as production — the only difference is that blockchain network confirmation is simulated, never real. No real Blockchain Transaction is ever created from a Sandbox, and no Sandbox data ever reaches Production.

Every simulation command requires the target Environment to be of type Sandbox — calling these routes against a Production Environment returns 422 ENVIRONMENT_NOT_SANDBOX, with no side effects. This is the central safety mechanism: it's not an error to avoid, it's the protection that makes it safe to test your integration without any risk to real money.

Faucet — instant test balance

The fastest way to get test balance: observes, credits, and confirms in a single step.

POST /v1/environments/{environmentId}/sandbox/faucet

Important: the depositAddress you send must be exactly the address returned by an already created Payment Intent for the Transaction you want to fund — the Sandbox only simulates the network arrival; the module that actually credits the Account's Available balance is Deposits, by resolving the Payment Intent for that address. An arbitrary depositAddress (with no matching Payment Intent) makes the Sandbox respond 200 normally, but Deposits silently ignores the event (address from another context) — no balance is credited. See Ledger and Transaction/Settlement for the full flow (Transaction → Payment Intent → Faucet/simulate-deposit).

Simulate a Deposit step by step

To test how your integration reacts to progressive confirmations (instead of the Faucet's instant credit), simulate each step separately:

  1. POST .../sandbox/simulate-deposit — records the observed transaction.
  2. POST .../sandbox/simulate-confirmation — records a network confirmation (call as many times as you like, controlling the confirmation count).

Check the state at any time: GET .../sandbox/observed-addresses/{id}.

Simulate a real Withdrawal's broadcast

A real withdrawals.request() call is Self-Custody end to end (see Self-Custody): it builds a SigningRequest for you to sign, exactly like Settlement. Once every leg is signed and submitted, the platform's all-signatures gate broadcasts automatically — simulate that broadcast's confirmation the same way you would for a Settlement leg: POST .../sandbox/simulate-broadcast-confirmation, using the broadcastAttemptId derived from that leg's own broadcastReference (poll GET /v1/signing-requests/{signingRequestId} until it appears — see self-custody-settlement.ts in the Mercatto example for the exact, real code, reused identically for Withdrawal legs).

POST .../sandbox/simulate-withdrawal (and its own GET .../sandbox/broadcast-attempts/{id}) is a separate, standalone simulation utility — it creates its own SandboxBroadcastAttempt, disconnected from any real Withdrawal/ExecutionLeg. Confirmed live: the real Self-Custody Withdrawal execution strategy never reads or writes it. Do not build a real Withdrawal integration test around it.

Adjust the Treasury's observed balance (reconciliation)

To test reconciliation scenarios (TreasuryReconciliation), the Sandbox lets you directly adjust the Treasury's observed balance for an Asset Network:

POST .../sandbox/treasury-balance

Why this is safe

Every simulation flows through the same real Workflow, Ledger, and Settlement — only the source of the network confirmation event changes (simulated, not a real blockchain). Your integration, tested in Sandbox, behaves exactly as it would in Production, with the same API, the same events, and the same data model.