outcome field). Customer-wallet crypto deposits on supported chains run on a real public testnet and are not simulated — you fund a wallet by sending real testnet crypto to its address from a faucet, and it is detected automatically (Use a real testnet). Tron and Stellar cannot receive a detected deposit on this posture. Deposit-funded orders must also receive real testnet transfers at their published funding address. See Sandbox overview for the full posture.
This page covers three deposit types, one per fundable resource:
- Fiat deposits land on a customer’s virtual account via a simulate endpoint. The deposit is ingested asynchronously; no bank transfer occurs.
- Crypto deposits on supported chains land on a customer’s wallet from a real testnet faucet sent to the wallet’s address. The deposit enters the same ingestion pipeline as any external deposit, including compliance screening and the sender-information gate. It cannot be simulated on the deployed sandbox.
- Deposit-funded order transfers land on the funding address the order publishes. The transfer is an ordinary
deposittransaction you can read back. See Deposit-funded orders for the concept.
Prerequisites
- A sandbox API key for an
activecustomer. SetSANDBOX_API_KEY,CUSTOMER_ID,VA_ID(virtual account), andWALLET_IDin your shell. - For fiat: the virtual account must be
active. Deposit in the currency it holds —USDon the sandbox accounts you get by default. - For crypto: the wallet must be
activeand have a deposit address. - Base URL:
https://api.sandbox.conduit.financial.
The
idempotency-key header is required on every money-moving POST. A
successful response is kept for 30 days — replay the same key to safely
retry; use a fresh key for a new operation.Fiat deposit — happy path
Inject a synthetic deposit into a customer’s virtual account, in the currency that account holds.POST https://api.sandbox.conduit.financial/v2/sandbox/customers/{customerId}/virtual-accounts/{virtualAccountId}/deposits/simulate
Request body:
202 Accepted means the deposit was handed to the ingestion pipeline. Ingestion is asynchronous — exactly as it is in production, where no endpoint creates a deposit synchronously — so the response body carries only externalReference: the sandbox_… reference the deposit is detected under. It is derived from your organization and the reference you sent, or from the deposit details when you omitted it. Send it back verbatim: the acknowledged reference — not your original string — is the one the deposit is stored under and the one the filter matches. Observe the deposit through the transaction.created webhook, or read it back with GET /v2/transactions?type=deposit&externalReference=…. Re-sending the same externalReference from your organization re-acknowledges the existing deposit rather than creating a duplicate. The customer’s USD balance updates within a few seconds, and your webhook endpoint receives transaction.completed.
Fiat deposit — compliance failure paths
Fiat deposits use the same suffix protocol as crypto deposits, matched against the last 8 digits of the sender’s bank account number (non-digit characters stripped). Pass asenderInfo.accountNumber ending in a documented suffix to force a specific compliance outcome.
The deposit-specific suffix values are listed in the Suffix catalog below. For the consolidated suffix table across deposits and withdrawals, see Scenario suffixes.
Crypto deposits
Send real testnet funds to the customer wallet address or to the funding address in a deposit-funded order’sdepositInstructions. The sandbox detects the transfer and credits it after chain finality and compliance checks. Use a supported chain and testnet faucet. Crypto deposit simulation endpoints are unavailable. Watch transaction.created or query GET /v2/transactions?type=deposit&chain=<chain>&txHash=<transfer-hash>.
For a deposit-funded order, register the sending address first. Send the order’s totalDebit to the published funding address before lockExpiresAt. A transfer from an unregistered address is returned. See Deposit-funded orders.
Resolving a held funding transfer
When a transfer into a funding address is held for compliance review, resolve it on the order:POST https://api.sandbox.conduit.financial/v2/sandbox/orders/{orderId}/deposits/simulate/compliance-decision
approve releases the hold and the funds go on to fund the order, which works even once lockExpiresAt has passed — the transfer arrived in time, so the order is still pending waiting on this decision; it is available only while the review is still open, and returns 409 once the review has already rejected the transfer — a rejected review can only be rejected. reject holds the funds permanently: they neither fund the order nor go back, the order is cancelled expired on the next sweep after the decision, and the transfer’s own transaction reads failed with no failureCode. 202 Accepted returns the order as of the call; poll GET /v2/orders/{orderId} for the outcome. 404 SANDBOX_ORDER_NO_PARKED_FUNDING means nothing is currently held for review.
For a full walkthrough — register the sender, create the order, read the address, fund it, watch it auto-execute — see Offramps.
Sender information for a real crypto deposit
When a real transfer needs sender information, the deposit waits at the sender-information gate. Send the originator details toPOST /v2/sandbox/customers/{customerId}/deposits/{depositId}/simulate/sender-info while it is pending. The sandbox timer expires after about 10 minutes; the webhook still reports the production deadline. See Use a real testnet.
Suffix catalog
Suffixes are matched against the last 8 characters of the source identifier:- Crypto deposits: last 8 hex characters of
sourceAddress(case-insensitive on EVM; Base58 verbatim on Tron and Solana). - Fiat deposits: last 8 digits of
senderInfo.accountNumber(non-digit characters stripped before matching).
Crypto deposit suffixes (matched on sourceAddress)
Fiat deposit suffixes (matched on senderInfo.accountNumber digits)
† On deposits, every non-CLEAR compliance classification (high-risk or sanctions match) holds the deposit for a compliance decision rather than failing it outright — it stays
pending until the decision lands, and it is never credited in the meantime. Resolve it in sandbox with POST https://api.sandbox.conduit.financial/v2/sandbox/transactions/{depositId}/simulate/compliance-decision and { "outcome": "reject" }, which freezes it; approve is not available on an already-rejected review. The public failure code is compliance_hold in all cases; the underlying classification is recorded on the dashboard for audit. If the fiat deposit is the source funding event for the oldest pending autoExecute: true ONRAMP order that matches the deposit tuple and its amount could cover that order’s total debit, that order also emits order.failed with reasonCode: "provider_rejected".
The
DEAA8157 suffix (crypto) and 95009003 suffix (fiat) trigger an
elevated-risk compliance classification that is recorded internally for audit.
At current thresholds this classification routes APPROVED on the public
surface, so there is no observable difference from a clean deposit. Use these
suffixes to exercise audit-trail emission only; do not branch your integration
logic on them.Webhook events
transaction.failed payloads carry a failureCode when the cause is actionable. transaction.awaiting_sender_information includes daysRemaining and deadlineAt — these always reflect the real 30-day deadline (the same values your production handler would see). Only the sandbox internal timer is compressed to ~10 minutes so the timeout path is fast to test.
Errors
See Errors for the full catalog. Deposit-relevant failure codes:VIRTUAL_ACCOUNT_ASSET_MISMATCH(422) — the fiat simulate body’sassetAmount.codeis not the currency the virtual account holds. Fetch the virtual account to read its currency, then resend with that code.compliance_hold— compliance screening returned a non-CLEAR decision (high-risk or sanctions match); the deposit is frozen and cannot be credited.returned_by_sender— the inbound transfer was returned by the originating institution before it could be credited. Sandbox triggers this branch via theoutcome: "returned"field on the deposit simulate endpoint.sender_info_timeout— the sender-information gate expired before details were provided; send a new transfer and provide sender information while it is pending.
Diagrams
Crypto deposit state machine
Sender-information gate — sandbox auto-pilot timeline
Related pages
- Sandbox overview — full sandbox posture and what’s mocked
- Withdrawal failure paths — compliance magic-suffix catalog for withdrawals and deposits
- Withdrawals — crypto withdrawal lifecycle and cosign flows
- Virtual Accounts — virtual account model and deposit instructions