txHash that appears on no explorer. You can instead opt a single offramp into a real broadcast on a public testnet, then verify the transfer on that network’s block explorer. Opting in is per request — it does not switch your whole sandbox to real broadcast, and omitting the header keeps the same order fully mocked. It also requires real testnet to be enabled on your sandbox and a wallet with real testnet custody.
Because the source transfer is now a real on-chain movement, the order 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 broadcast covers
- It applies to the crypto source leg of any order on
POST /v2/ordersthat is funded from a crypto wallet — an offramp, or a crypto conversion. That source transfer leaves the wallet on a real testnet; the conversion and fiat-payout legs stay mocked. - It is the order path, not a plain withdrawal.
POST /v2/payoutsnever reads the header — a sandbox payout is always simulated. Onramps do not qualify either (an onramp is funded from a virtual account, not a wallet). - It is a sandbox feature — send it only against the sandbox host, never 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. Adding more wallets to a mock customer does not change this — they reuse that customer’s custody account. A real-capability attempt on a mock wallet fails cleanly and moves no funds: a real broadcast is refused at order creation with422 SANDBOX_REAL_BROADCAST_UNAVAILABLE, and a passkey signature with 422 PASSKEY_SIGNING_UNAVAILABLE. 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 CLAIM_RESET_BLOCKED_NONZERO_BALANCE) — 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 does not apply here, and returns 409 SANDBOX_SIGNING_SIMULATION_UNAVAILABLE once real testnet is enabled). How you approve depends on the wallet’s signingMode:
passkey_required— a person approves through the signing link delivered on thetransaction.awaiting_signaturewebhook.programmatic— your backend approves with a machine stamp atPOST /v2/signing-requests/:id/approve(a person with a passkey still can).programmatic_unattended— same machine approval, and no human is in the path. It is not self-serve: Conduit enables it per customer after a legal sign-off. A programmatic wallet with a machine-only signer roster has no human signing link, so itstransaction.awaiting_signaturelink answers409 SIGNING_LINK_NOT_HUMAN_SIGNABLE.
Supported testnets
Real testnet broadcast is not supported on Tron or Stellar. The API does not reject the header on those chains, but an opted-in Tron or Stellar order fails later rather than running mocked, so omit the header there.
End-to-end walkthrough
Prerequisites: a sandbox API key, and the base URLhttps://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’saddress 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’saddress. Gas is sponsored on every supported chain, so you never fund native ETH, POL, or SOL yourself.
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. PollGET /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 at or above the Travel Rule threshold, or from certain source addresses, parks awaiting sender information and emits
transaction.awaiting_sender_information. Provide it with POST /v2/transactions/:id/sender-information to release the deposit. In sandbox the deadline is compressed to about ten minutes (the webhook’s deadlineAt and daysRemaining still show the live 30-day contract), so clear it promptly:
The gate mechanics, the deterministic sandbox drivers, and the manual sandbox clear lever are covered in full under Deposits — the sender-information gate.
4. Opt in and raise the offramp
Once the deposit has credited, create an OFFRAMP order withX-Sandbox-Real-Broadcast: true (the value is case-insensitive and trimmed; any other value, or omitting it, keeps the order mocked). The full request body is in OFFRAMP orders in sandbox — the only difference here is the header:
202 with the order pending. Use a fresh idempotency-key when you add the header. The header is part of the idempotency fingerprint, so re-using the key from an earlier mocked attempt does not opt that order into real broadcast — with the header now set it is a different request and returns 409 IDEMPOTENCY_KEY_CONFLICT.
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 thetransaction.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’sorder.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. The API does not reject the header on those chains, but an opted-in Tron or Stellar order fails later rather than running mocked — omit the header there.
- 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.
- A deposit that times out on the sender-information gate is terminal: its funds are never credited and cannot be recovered through the API.