How to Test Crypto Payments in a Sandbox Before Going Live

A step-by-step plan to test crypto deposits, payouts and error cases in a sandbox with fake money, so your first real payment works the first time.

On a blockchain, a mistake is final. If your code sends a payout to the wrong address, or sends it twice, there is no bank to call and no "reverse" button. That is why the first real payment your app makes should not be its first payment at all.

A sandbox is a copy of the platform that runs on fake money. You get a separate key, a separate database and the same API. You can break things there as often as you like, and nobody loses a cent.

This guide shows how to use a sandbox well: what to test, in what order, and the mistakes that still slip through when people test only the happy path.

#What a good sandbox gives you

Not every test mode is equal. Some only return canned answers, so your code passes in testing and then meets a new error on day one of real traffic. A useful sandbox should:

Our sandbox is built this way. A simulated deposit is a real deposit record pushed through the real crediting logic, with your fees and the deposit minimum applied. A sandbox payout walks the real state machine, from queued to confirmed, just without a chain underneath. The test data lives in its own database, and the live ledger never sees it.

#Step 1: get a sandbox key

You can get a sandbox key with one request, no signup needed:

bash
curl -sX POST https://merchant.cryptoinfra.build/sandbox/v1/signup-key

The response gives you an api_key that starts with ck_sandbox_, and the base_url to use. Put both in environment variables, never in your code:

bash
export CRYPTOINFRA_KEY=ck_sandbox_your_key
export API=https://merchant.cryptoinfra.build/sandbox

Going live later means changing these two values and nothing else. If your code needs a code change to go live, something is hard-coded that should not be.

#Step 2: test your webhook handler on its own

Today the sandbox does not deliver webhooks. That is fine, because a webhook handler is easy to test without us, and it is better tested in isolation anyway.

Pick a test secret. Write a small script that takes a sample event body, signs the exact bytes with HMAC-SHA256 and that secret, and posts it to your handler with the x-cryptoinfra-event and x-cryptoinfra-signature headers. Now you can send a good event, a repeated event and a forged one whenever you like. Our guide on receiving crypto webhooks safely shows the event bodies and the signature check.

While you test against the sandbox, let your app learn results by reading the API, as the next steps do. That is the habit you want in production too.

#Step 3: create a user and fund them

Create a user with the id they have in your own system. They get a permanent TRON address.

You cannot send real USDT to a sandbox address, so the sandbox has a faucet instead:

bash
curl -sX POST $API/v1/simulate/deposit \
  -H "Authorization: Bearer $CRYPTOINFRA_KEY" \
  -H "Content-Type: application/json" \
  -d '{"external_user_id":"<your user id>","asset_id":"usdt_trc20","amount":"<amount>"}'

This credits the user through the same logic a real transfer goes through. Read GET /v1/users/{id}/balances to see it land. Try it with USDT, USDC and TRX, because each asset has its own decimals and its own minimum.

#Step 4: send a payout and watch it finish

Ask for a fee quote, then send a withdrawal with an idempotency_key. You get 202 and the status queued. A few seconds later the sandbox moves it through signing and broadcast to confirmed.

Read the withdrawal with GET /v1/withdrawals/{id} until it is final. Get into the habit now: in production a webhook will tell you sooner, but the read is always the answer. See the payouts page for how statuses work end to end.

#The test plan: more than the happy path

Most bugs live in the cases that "never happen". The sandbox is where you make them happen on purpose. Work through this list before you go live:

TestWhat you should see
Simulate a normal depositStatus credited, balance goes up
Simulate a deposit below the minimumStatus ignored_dust, no credit, no surprise
Post the same signed event to your handler twiceIt credits only once
Post an event with a wrong signatureYour handler rejects it
Send a payout, then repeat it with the same keyOnly one payout exists
Repeat the key with a different amount409 idempotency_conflict
Send a payout larger than the balance409 insufficient_balance, nothing queued
Send to an invalid address400 invalid_address, nothing queued
Kill your payout worker mid-request, restart itIt reuses the stored key, one payout

The dust case matters more than it looks. A deposit below the asset's minimum is not credited, in the sandbox and in production alike. If your app shows "payment received" from your own records before the platform credits it, this is where you will find out.

#What the sandbox does not cover

Be honest about the gaps, so they do not surprise you later:

#Going live: a short checklist

#Common mistakes

MistakeWhat goes wrongFix
Testing only the happy pathThe first real error breaks productionRun the full test plan above
Hard-coding the sandbox URLLive traffic goes to the sandboxRead it from the environment
Skipping signature checks "for now"They never get addedVerify signatures from day one
Keeping your test signing secretLive events fail to verifyUse the secret your live endpoint gets
Copying a fee from a test runUsers see a wrong numberAlways show the live quote

#In summary

A sandbox is cheap insurance. Get a key, fund a user with the faucet, push payouts through every status, and test your webhook handler with events you sign yourself. Then break things on purpose: repeat events, reuse keys, send too little and too much. When all of that behaves, going live is a change of two settings.

The quickstart in our docs has every call in order, and the developer overview shows the rest of the API.

Ready to build crypto payments under your own brand? Sign up free and start testing in the sandbox today.

Launch your own crypto brand.

Wallets, payouts, cards and swaps under your name. Start free and test in the sandbox.