txHash is verifiable on the network’s block explorer, it takes minutes to reach finality rather than seconds, and it can occasionally be delayed before it settles.
The fiat-in and crypto-delivery legs both originate inside Conduit (there is no external actor delivering fiat, and the customer does not send the crypto), so there is no mid-flow injection lever for them. Use orders/:id/simulate/conversion-failed (below) to drive the whole order to a failed terminal state, or create the pending auto-execute order first and then inject a source fiat deposit whose senderInfo.accountNumber carries a failure suffix — see Deposits and Sandbox overview.
Prerequisites
- An
activecustomer with at least one virtual account for the source fiat asset. Follow Sandbox quickstart if you haven’t set this up yet. - Your sandbox API key exported as
SANDBOX_API_KEY. - The customer’s virtual account ID exported as
VA_ID.
Lifecycle overview
An ONRAMP order moves through these stages: the order is created and rate-locked → the source (fiat-in) and destination (crypto-out) conversion legs finalize automatically →order.succeeded fires. The conversion sub-leg is covered in detail on /sandbox/conversions.
Because both legs are internal movements in sandbox, there are no manual settle calls in the happy path. Use orders/:id/simulate/conversion-failed to force the order to a failed terminal state, or create the pending order and then simulate a source fiat deposit with a deposit suffix.
Intermediate state is observable only via GET /v2/orders/:id (poll). Terminal status surfaces via webhook: order.succeeded or order.failed or order.cancelled.
Full happy path
Step A — Create the order
Create the order by supplying the source virtual account (USD), the destination wallet (USDC), the lock side, and the amount. SetautoExecute: true to let the platform begin execution immediately. The example uses a small amount (1.00) so the crypto it delivers stays under the per-chain, per-UTC-day liquidity cap a new customer has — a larger amount is refused with 422 SANDBOX_ONRAMP_DAILY_CAP_EXCEEDED. See Errors for the cap and how to free headroom.
202 Accepted. Capture id as ORDER_ID. The fiat-in leg finalizes synthetically; the crypto delivery leg then settles — on a real testnet (minutes, real txHash, can be delayed; see the warning above). Webhook: order.succeeded (status: succeeded) fires once delivery reaches finality. No manual settle calls are needed; poll GET /v2/orders/$ORDER_ID while the delivery confirms.
GET /v2/orders/$ORDER_ID to observe progress if needed. No webhook fires for intermediate leg state — only terminal outcomes emit a webhook.
Simulate conversion failure
Force the in-flight conversion to fail regardless of which leg it is waiting on. The order terminates infailed; any funds already debited from the source are returned automatically.
200 OK returning the order at its current state. Webhook: order.failed carrying orderId, customerId, clientReferenceId, reasonCode, failureMessage (the standard text for that reasonCode, as in production), and failedAt. The reason you supply is kept as the note on the cancelled transfer, not on the order. See /sandbox/conversions for more detail.
Source-deposit compliance failure
For unfunded ONRAMP tests, create the order withautoExecute: true, then inject the fiat source deposit through the deposits simulator with senderInfo.accountNumber ending in 95009001 or 95009002. The deposit freezes with transaction.failed and failureCode: "compliance_hold", and the oldest pending auto-execute order that matches the deposit and is amount-covered emits order.failed within a few seconds. orders/:id/simulate/conversion-failed remains the lever for conversion-level failures after the order has begun executing.
Simulate rate-lock expiry
Backdates the order’s rate-lock timestamp so the next sweep cycle treats the lock as expired. The order transitions tocancelled with cancellationReason: "expired".
200 OK returning the order at its current state. Webhook: order.cancelled with cancellationReason: "expired". Cancellation lands within ~1 second via an immediate background sweep tick. No need to wait for the scheduled 30-second sweep.
This endpoint enqueues an immediate sweep tick so you can verify your integration handles rate-lock expiry without waiting for the live lock window to elapse.
Order status reference
Intermediate steps (source settled, conversion in progress) are not reflected as order statuses and do not emit webhooks. Poll
GET /v2/orders/{orderId} for current state; only the terminal outcomes (succeeded, failed, cancelled) surface via webhook.Webhook events
Errors
Each customer has a cap on the net crypto they can draw from sandbox’s shared testnet liquidity, tracked per chain and per UTC day, which keeps that liquidity available across customers. An onramp (and the outbound leg of a cross-chain conversion) draws liquidity down; an offramp (and the inbound leg of a conversion) returns it and frees the customer’s headroom on that chain. An onramp or conversion that would carry the customer’s net draw for the day over the cap returns422 SANDBOX_ONRAMP_DAILY_CAP_EXCEEDED at order creation or execution. A new customer’s default is about $2 of net crypto per chain per day, so keep test amounts small; ask support to raise it. The cap resets at each UTC midnight: the previous day’s completed draws stop counting and headroom is full again on every chain, except for an onramp still in flight that keeps its reservation until it settles or fails. To free headroom sooner for a priced asset, return crypto with an offramp on the same chain. A testnet asset with no USD price is capped by a per-day transaction count instead; returning crypto does not lower that count, so wait for the next UTC day or ask support to raise it.
Simulate endpoints return 404 ORDER_NOT_FOUND when the order does not exist or belongs to a different organization. Replays against an already-terminal order return 200 with the order at its current state (idempotent). If execution has not yet started, the simulator arms the failure for when it does. See /errors for the full error shape. The order.failed payload carries reasonCode (insufficient_funds / provider_unavailable / provider_rejected / internal_error / cancelled) describing the failure category.
Sequence diagram
Related pages
- Sandbox quickstart — set up customer, virtual account, and wallet in under 5 minutes
- OFFRAMP orders — crypto-in → fiat-out counterpart
- Conversions — conversion sub-leg reference
- Sandbox overview — full sandbox posture and what is synthetic
- Webhooks reference — full payload schemas for all
order.*events - Errors — RFC 9457 error shape and
failureCodecatalog