Skip to main content
The deployed public sandbox (https://api.sandbox.conduit.financial) runs real testnet for crypto: on a supported testnet chain (Base, Ethereum, Polygon, Solana — see Supported testnets below) a crypto transfer both broadcasts and is signed on a public testnet, and you verify it on that network’s block explorer. A crypto transfer is no longer mocked — it is a real on-chain movement. (Tron and Stellar do not broadcast on this posture.) Real testnet is a property of the whole sandbox cluster, not a per-request choice, and it applies to the customers and wallets you provision while it is on. It requires a wallet with real testnet custody, so a customer you provision now gets it; a customer provisioned before real testnet was enabled stays mocked (a synthetic txHash that appears on no explorer) with no upgrade path — see Before you start. Because a crypto transfer is now a real on-chain movement, it runs the same compliance, finality, and signing steps a live crypto flow runs. This page walks the whole path and calls out the traps that a mocked run never hits.

What real testnet covers

  • It applies to every crypto transfer that leaves a wallet: the crypto source leg of an offramp or a crypto conversion on POST /v2/orders, and a crypto withdrawal on POST /v2/payouts. Those transfers move on a real testnet and need a real signature; the FX conversion sub-leg and the fiat-payout leg stay mocked.
  • It also applies to crypto delivered into a wallet by Conduit: the delivery leg of an onramp (Conduit → customer wallet) and the destination leg of a crypto conversion are real on-chain transfers too. The customer signs nothing for these (Conduit sends them), but they broadcast a real txHash, take minutes to finalize, and can occasionally be delayed before they settle.
  • It is a sandbox feature — real testnet runs only on a sandbox cluster, never on the live API.

Before you start

A customer with real testnet custody. Real testnet custody is fixed when a customer’s wallet account is first provisioned — which happens when you create the customer’s first wallet, and is shared by every wallet after that. A customer whose account is first provisioned while real testnet is enabled on your sandbox gets real testnet custody, so its wallets can sign on a real chain; a customer whose account was provisioned before that stays mock permanently, by design, with no upgrade path. Once real testnet is enabled on your sandbox, a mock customer can no longer add wallets, and a mock wallet can no longer transact at all: a new wallet for that customer, and any payout or order funded from a mock wallet, is refused with 422 LEGACY_MOCK_WALLET_UNSUPPORTED, telling you to recreate the wallet under a new sandbox customer. To use real testnet, create a new sandbox customer and create its first wallet now — do not try to reuse a mock customer, whose claim is refused with 409 CUSTOMER_ALREADY_CUSTODIAL or 409 CUSTOMER_ALREADY_NON_CUSTODIAL. An earlier customer can sometimes be reset with POST /v2/sandbox/customers/:customerId/simulate-reset-claim, but the reset is refused while anything still references its wallets (409 CLAIM_RESET_BLOCKED) or a custodial wallet holds a balance (409 CONFLICT) — a new customer is the reliable path. A way to sign for real. A real broadcast is signed through the wallet’s normal payout approval, not the sandbox cosign shortcut (simulate/cosign returns 409 SANDBOX_SIGNING_SIMULATION_UNAVAILABLE). How you approve depends on the wallet’s signingMode:
  • passkey_required — a person approves through the signing link delivered on the transaction.awaiting_signature webhook.
  • programmatic — your backend approves with a machine stamp at POST /v2/signing-requests/:id/approve (a person with a passkey still can).
  • programmatic_unattended — same machine approval, and machine admins too, so a roster can run with no human in the path. On live this is not self-serve: Conduit enables it per customer after a legal sign-off. On sandbox it is the default a new organization already has — no sign-off, nothing to request — so a customer you provision now resolves to programmatic_unattended and claims with a machine-signer roster out of the box (see Quickstart Step 5.2 and Multi-signer wallets). A programmatic wallet with a machine-only signer roster has no human signing link, so its transaction.awaiting_signature link answers 409 SIGNING_LINK_NOT_HUMAN_SIGNABLE.

Supported testnets

Real testnet broadcast is not supported on Tron or Stellar. In a deployed real-testnet sandbox a crypto transfer on Tron or Stellar fails rather than running mocked. Tron is refused before anything is created. POST /v2/quotes, POST /v2/orders and POST /v2/payouts answer 422 CHAIN_NOT_SUPPORTED when either side, or the payout destination, is on Tron. No quote, order or payout is created. A Stellar wallet does receive on the real-testnet sandbox. It receives testnet USDC once it reads status: "active". A non-custodial Stellar wallet reads pending until its signers approve a one-time on-chain setup, which the wallet.awaiting_setup_signature webhook announces (see Stellar setup).
A Tron wallet still reports status: "active" once created. On this posture active means the wallet exists and has an address, not that it can receive or transact — a deposit to it is never detected. Do not treat the active status, or the presence of an address, as evidence that a Tron wallet can receive funds.

End-to-end walkthrough

Prerequisites: a sandbox API key, and the base URL https://api.sandbox.conduit.financial.

1. Create a customer and a wallet

Create a new customer (for real testnet custody, see Before you start), then a crypto wallet on a supported chain (Add a crypto wallet). The wallet object’s address is a real address on that chain’s testnet — capture it as the address you will fund. An EVM address is shared across Ethereum, Base, and Polygon because those wallets share one key, but each chain is a separate wallet resource with its own id and its own balance. Funds are only spendable by the wallet on the chain you sent them to, so fund the chain the wallet is on — the same 0x… address on another chain holds a different balance.

2. Fund the wallet from a faucet

A real broadcast spends real testnet funds, so send the asset you will move — for example test USDC — to the wallet’s address. Gas is sponsored on every supported chain, so you never fund native ETH, POL, or SOL yourself. Crypto deposit simulation routes are unavailable. Fund the wallet with real testnet tokens from a faucet.

3. Let the deposit clear

The inbound faucet transfer is a real deposit, so it passes two gates before its balance is spendable — the same gates a live deposit passes. Chain finality. The balance stays pending until the transfer is final on its network. Poll GET /v2/transactions/:id (or watch transaction.completed) until it credits. These are the network’s real thresholds — the same ones live uses — so a testnet deposit can take a few minutes. A deposit that does not reach finality in about ten minutes parks for an operator instead of crediting; re-fund a fresh wallet to continue. The sender-information gate. A deposit can park awaiting sender information and emit transaction.awaiting_sender_information. Into a customer wallet it parks when the sender is not registered (any amount), when the amount is 10,000 units or more (even from a registered sender), or when sourceAddress ends in DE5E11F1. A transfer into the funding address of a deposit-funded order never parks: an unregistered sender, or a sourceAddress ending in DE5E11F1, is returned as a deposit_return. Provide it with POST /v2/transactions/:id/sender-information to release the deposit. In sandbox the deadline is compressed to about ten minutes. After it, the deposit stays held until you clear it:
Until the gate is cleared, the deposit balance is not credited. Do not expect a small amount to skip the gate here: the deployed sandbox runs with no Travel Rule dollar threshold, and a faucet deposit arrives from an address the customer has not registered, so it parks at awaiting_sender_information (waitingOn.reason = unregistered_address) regardless of the amount. Clear it promptly with POST /v2/transactions/:id/sender-information.
The gate mechanics, the deterministic sandbox drivers, and the manual sandbox clear lever are covered in full under Deposits — the sender-information gate.

4. Raise the offramp

Once the deposit has credited, raise the OFFRAMP order. Under most organization policies a payment_for_goods_or_services payout needs a supporting document first, so upload one and pass its doc_... id in autoPayout.documents. Upload it with a multipart request — replace the file with your own:
The response carries the document’s doc_... id. Now create the order — this is a full request body; replace the wallet id, the virtual-account id, the doc_... id, and the recipient with your own. For the full field reference and variations (deposit-funded, other rails), see OFFRAMP orders in sandbox:
The response is 202 with the order pending. Without the documents id most policies refuse creation with 422 DOCUMENTATION_REQUIRED; if your organization’s policy does not require a document for this purpose, you can omit it. To skip documents another way, use "purpose": "intercompany" with a recipient already on the customer’s whitelist. See OFFRAMP orders — Step A for the document policy.

5. Approve the signature

The source transfer is a real crypto movement, so it waits for the wallet’s signature (see Before you start): approve through the transaction.awaiting_signature signing link for a passkey wallet, or with a machine stamp at POST /v2/signing-requests/:id/approve for a programmatic wallet.

6. Verify on a block explorer

The order’s order.succeeded webhook carries the source transfer’s real testnet txHash — the on-chain hash of the offramp source leg. Open it on the testnet’s explorer; that on-chain entry is the proof the broadcast was real: A mocked offramp, by contrast, returns a synthetic txHash that resolves on no explorer.

Limitations

  • Real testnet broadcast is not supported on Tron or Stellar: a crypto transfer on either chain fails rather than running mocked. A quote, order or payout on Tron is refused with 422 CHAIN_NOT_SUPPORTED. A Tron wallet cannot receive on the real-testnet sandbox; a Stellar wallet receives testnet USDC once it reads active.
  • Real testnet custody is fixed when a customer’s account is first provisioned and has no upgrade path: a customer provisioned before real testnet was enabled stays mock. To broadcast, create a new sandbox customer — see Before you start for the details and recovery options.
  • Automated testnet deposit detection runs against a shared capacity limit, so at high volume a testnet deposit can be detected with some delay.

See also