source.network (and, later, destination.network): the order itself lives on a native settlement network, and a cross-chain intent provider carries funds between the rail and the settlement network. Assignment, payout and settlement are exactly the native flow.
Rails are discovered from GET /v2/tokens, described on the order by a bridge object, and tracked with two extra webhook events. None of that is specific to a direction: the same fields describe an off-ramp deposit on a rail and, when available, an on-ramp payout to one. Which networks are rails, and for which tokens, is whatever GET /v2/tokens reports.
Which networks are rails
GET /v2/tokens marks a rail with one extra field, settlementNetwork; its presence is what tells you the row is a rail, and its value is where an order funded here settles and is priced. A token without it is a native network. Rails are per token, not per network: the same origin network can carry one symbol to one settlement network and another symbol to a different one, because a bridge does not route every symbol to every chain. Always read settlementNetwork from the token row you are about to use. The examples on this page use the Solana USDC rail settling on Base.
bridge.provider, which is where to read it — for a support conversation, or to tell your own users who moves their funds.
A rail can be switched off operationally. When it is, the token is listed without settlementNetwork and a create with that network is rejected exactly as before the rail existed. A symbol that is not configured on an otherwise live rail is refused with 400 Source — “Provided token or payment rail is not supported”.
Off-ramp on a rail
The user deposits on the rail; the bridge delivers the settlement-network amount to the order’s receive address, and the native off-ramp flow takes over from there.Create the order
Use the normal off-ramp payload with the origin chain insource.network and a refund address on that chain:
amount, rate, senderFee, provider pinning and everything else behave as on a native network. amount is still what settles on the settlement network; amountIn: "fiat" works too.
What comes back
providerAccount.amountToTransfer of providerAccount.currency on providerAccount.network to providerAccount.receiveAddress before validUntil, and to include providerAccount.memo whenever it is present (some chains share deposit addresses and need it).
A rail deposit is an ordinary transfer on the origin chain, so the sender pays its gas:
amountToTransfer covers the transfer itself and nothing else. Deposit addresses are per quote, so on Solana the sender also pays the one-off cost of creating the deposit address’s token account — currently about 0.0015 SOL, roughly 300× the signature fee a wallet quotes, and not refunded. A wallet holding the token but no native balance refuses before broadcast, with an error that does not mention Paycrest.Track the bridge
The order’sstatus is unchanged by the bridge: it stays initiated until the delivery lands on the settlement network and is credited, then follows the normal lifecycle. Bridge progress is on bridge.forward.status:
bridge.forward.amountIn is the quote — what the sender was told to send — and is never rewritten, so it still reads the same after the order settles. Once the bridge reports a deposit, bridge.forward.depositedAmount carries what actually arrived. Compare the two to see whether the user over- or underpaid; they differ slightly in normal operation, since the bridge deducts its intake fee before the swap.
Two webhook events cover the hops. Neither changes data.status, so branch on event:
payment_order.bridge_deposit_detected— the origin deposit was seen (bridge.forwardmoved toknown_deposit_tx/processing). A good moment to tell the user “we’ve got it, bridging now”.payment_order.bridge_refunded— a refund reachedsource.refundAddresson the origin chain (bridge.reverse.status = success).
payment_order.deposited event, exactly like a direct deposit.
Refunds
Refunds always go back tosource.refundAddress on the origin chain. There are two paths:
- Before delivery (deposit too small, sent after the deadline, or the bridge could not route it): the bridge refunds the origin deposit directly. The order becomes
expiredandbridge.forwardrecordsrefundedAmount/refundReason. Nobridge.reverseis created. - After delivery (the provider queue was exhausted or the order was refunded on the settlement network): the order becomes
refundedas usual, and Paycrest then carries the settlement-network balance back with a reverse hop.bridge.reverseappears with the same fields asforward; when it reachessuccessyou receivepayment_order.bridge_refundedandbridge.reverse.destinationTxHashis the origin-chain tx.
payment_order.refunded therefore means “refund on the settlement network”; the user has the funds only after payment_order.bridge_refunded. Balances too small to bridge economically stay in Paycrest custody as bridge.reverse.status = dust and are handled by operations.
Timing
providerAccount.validUntil(=bridge.forward.deadline) is the bridge’s deposit window. Deposits after it are refunded by the bridge.- The order stays creditable for a delivery grace period beyond the deadline, and Paycrest extends it further once a deposit is seen, so an on-time deposit is never expired mid-delivery. The usual “expired after
validUntil” copy does not apply to bridge rails. - Delivery typically completes within a few minutes of the deposit confirming.
Errors
Explorer links
source.network is the origin chain; the order’s txHash and bridge.forward.destinationTxHash are on bridge.settlementNetwork. Link bridge.forward.originTxHash and bridge.reverse.destinationTxHash to the origin-chain explorer and everything else to the settlement-network explorer.
On-ramp on a rail
Not available yet. When it is, a rail will be accepted indestination.network and the same bridge object will describe the hop from the settlement network to the user’s rail address, using the same statuses and events as above. Until then, on-ramp orders use native networks only and a rail in destination.network is rejected as it is today.