Platform ToolsSandbox Testing

Sandbox Testing

Simulate verification decisions, treasury funding, and deposits, and rehearse every failure path before real money moves.

What the sandbox is

https://sandbox.rasto.co with an sk_test_ key is the full product with everything behind the API simulated. Same endpoints, same objects, same statuses, same webhooks, really delivered and really signed. Verification decisions and bank deposits are driven by you, through simulation endpoints under /api/sandbox/simulate/*.

On the live host every simulator returns 403 sandbox_only.

Sandbox and production, precisely

DimensionSandboxProduction
Endpoints, objects, statuses, error envelopesIdenticalIdentical
WebhooksReal: delivered and signed like productionReal
VerificationYou decide, through the simulatorDecided by the real review
Bank depositsSimulated with simulate/fiat_depositReal ACH and Fedwire credits
Wallet addressesDerived the same way, on testnetsDerived the same way, on mainnets
On-chain deliverySimulatedReal transactions
Treasury inventoryYou fund it with simulate/treasury_fundingFunded operationally
Exchange rateFixed and deterministic. USD to USDC is at parLive market rate plus spread
Simulation endpointsAvailable403 sandbox_only

Everything your code touches behaves identically, so a green sandbox integration is production ready.

Verification decisions

You are the decision engine in sandbox. The simulator runs the same shared decision path a real decision takes: statuses, per-requirement updates, and webhooks all behave identically.

curl -s $BASE/api/sandbox/simulate/verification_decision \
  -H "Api-Key: $KEY" -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{"customer_id": "cus_...", "decision": "approved"}'
decisionSimulatesWhat to test
approvedA clean passThe happy path, and endorsement.approved. Requested endorsements approve alongside
request_for_informationA retryable issue on proof of addressYour requirement-bucket UI and the PATCH-then-submit loop
rejectedA final adverse decisionYour terminal-state handling

The customer must already have a verification round, so call POST /api/customers/{id}/verifications/submit first. Otherwise the simulator returns 400 verification_not_started.

Treasury funding

Deliveries come from prefunded inventory, and the sandbox treasury starts empty. Fund the corridor you are testing first.

curl -s $BASE/api/sandbox/simulate/treasury_funding \
  -H "Api-Key: $KEY" -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{"asset": "usdc", "chain": "solana", "amount": "10000"}'

Forgetting this is the most common sandbox surprise: deposits park in orchestrating, exactly as they would in live during an inventory gap, until inventory exists.

Bank deposits

curl -s $BASE/api/sandbox/simulate/fiat_deposit \
  -H "Api-Key: $KEY" -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{"virtual_account_id": "va_...", "amount": "100.00",
       "sender_name": "ANA SILVA", "remittance_info": "invoice 42"}'

The deposit arrives on the account's own rail and runs the real pipeline: deposit, conversion, payout, with every webhook. Assert on the conversion's fee_lines and delivered_amount in your integration tests.

Magic amounts

Failure paths need no special endpoints. Specific amounts trigger them.

AmountResult
666.00Deposit returned, with the deposit.returned webhook
777.00Deposit on_hold, with the deposit.on_hold webhook
anything elseNormal orchestration

For the two magic amounts the status callback fires and no orchestration runs, so the response carries no workflow id.

Wallet deposits

Credit a held wallet directly, as if a deposit landed on chain:

curl -s $BASE/api/sandbox/simulate/wallet_deposit \
  -H "Api-Key: $KEY" -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{"wallet_id": "wal_...", "asset": "usdc", "amount": "250.00"}'

This writes the same wallet_transaction row a real delivery would, so balances and history read back through the code path you will use live, and wallet.deposit_received fires.

A complete test checklist

Onboarding

Terms accepted, customer created with documents, submitted. Handle approved, request_for_information plus the PATCH-then-submit loop, and rejected. Also assert the 422 verification_incomplete you get from submitting too early.

Money

Treasury funded, deposit landed. Verify the delivered amount, the fee_lines, and the tx_hash. Then run 666.00 and 777.00.

Wallets

Create a wallet, credit it with simulate/wallet_deposit, read the balance back, and run one operation end to end including the verify step. Let one operation expire on purpose.

Webhooks

Every event kind processed idempotently. Replay one from the portal to prove your dedupe works, and shuffle two events to prove your ordering uses sequence.

Failure hygiene

Retry a POST with the same Idempotency-Key and expect a replay, not a duplicate. Reuse a key on a different body and expect the 422. Send a request with no key and expect the 400.

When all five pass in sandbox, work through Going Live.