Skip to main content
Fiat deposits on this page are simulated: the balance is credited synthetically, with no real banking connection or third-party vendor calls, and the outcome is driven by your request data (account-number suffixes or an explicit 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 deposit transaction you can read back. See Deposit-funded orders for the concept.
Use fiat deposits when testing order-funded flows (onramps, conversions). Use crypto deposits when testing the inbound wallet flow including compliance and Travel Rule sender-info scenarios. Send funds to the published address when an order does not debit a named wallet.

Prerequisites

  • A sandbox API key for an active customer. Set SANDBOX_API_KEY, CUSTOMER_ID, VA_ID (virtual account), and WALLET_ID in your shell.
  • For fiat: the virtual account must be active. Deposit in the currency it holds — USD on the sandbox accounts you get by default.
  • For crypto: the wallet must be active and 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 a senderInfo.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’s depositInstructions. 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 to POST /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).
Addresses and account numbers not matching any suffix take the happy path: compliance approved, deposit completes.

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’s assetAmount.code is 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 the outcome: "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