Skip to main content
An ONRAMP order converts a customer’s fiat deposit into a crypto asset. The fiat-in leg is synthetic — no real bank transfer, deterministic and instant. The crypto delivery leg (Conduit → the customer’s wallet) is different on the deployed sandbox: for a real-testnet customer it is a real on-chain transfer, so the delivered 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 crypto delivery is real on-chain (real-testnet customers). order.succeeded no longer fires “within seconds” — the delivery broadcasts on a real testnet and waits for finality (minutes). The customer signs nothing (Conduit sends the delivery), but the transfer is real: the credited txHash resolves on the explorer, and the wallet balance moves on-chain. The delivery can occasionally be delayed before it settles — for example while it waits for shared testnet liquidity on that chain. A short delay clears on its own; poll GET /v2/orders/:id or watch order.succeeded. But if the order stays pending well past normal finality time, the delivery is held awaiting that liquidity and does not always resume on its own — contact support to have it released or returned. See Use a real testnet.
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 active customer 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. Set autoExecute: 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.
Poll 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 in failed; 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 with autoExecute: 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 to cancelled 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 returns 422 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