Order lifecycle
Every swap and bridge response is a snapshot of a durable order. Store its orderId, use the appropriate read endpoint, and render customerState rather than predicting the next step from elapsed time.
Statuses
| Status | Meaning for an integration |
|---|---|
awaiting_deposit | Nothing has arrived yet. Show the returned source funding instruction. |
awaiting_xmr1 | Show the XMR1 funding instruction. |
awaiting_trx1 | Show the TRX1 funding instruction. |
processing | A deposit has been seen and the order is moving. Continue tracking. Do not predict completion from elapsed time. |
completed | Render the resolved outcome; use customerState for presentation. |
failed | Render the failed outcome unless customerState declares another current recovery state. |
expired | Render expiry unless customerState declares an exact refund recovery action. |
refunded | A refund workflow completed. |
needs_review | Legacy value kept for wire compatibility; current API versions no longer emit it — treat it like processing if ever encountered. |
status is the coarse business outcome used for reporting and compatibility. customerState is the exhaustive display/action state machine. Its processing stages are deliberately generic (confirming, routing, trading, sending, refunding). confirmations and requiredConfirmations remain optional facts.
status is derived, not stored—no column holds processing—and every surface derives it the same way: an order past its deposit and not yet terminal reads processing, on the per-order read and in the session list alike. So awaiting_deposit means what it says on both: nothing has been observed arriving for this order. A deposit that is seen but not yet confirmed is already processing; confirmations and requiredConfirmations, not status, are how you tell those two apart.
Read the current order
| Order type | Durable REST read | Optional WebSocket upgrade |
|---|---|---|
| Swap | GET /v2/swaps/{id} | GET /v2/swaps/{id}/events |
| Native bridge | GET /v2/bridges/{id} | GET /v2/bridges/{id}/events |
Both read endpoints require either the owning session (x-session-id) or the exact destination address as the single-order verify query value. An order ID alone is insufficient. The verify path is read-only. A missing order and an absent or invalid credential intentionally produce the same 404 response, so do not infer that an order exists from a failed read.
See live updates for the WebSocket transport, opaque close behavior, and REST polling requirement.
Pauses and customer actions
customerState.kind === "paused" carries one safe reason for wait/support copy. It is a plain display string, nothing more.
customerState.kind === "action_required" is the only authority for an interactive control. Currently supported actions are coinflip and refund_address; use the separately validated coinflip or refundRecovery resource for the form/game data. Never infer an action from status, resource presence, or elapsed time.
Session lists and bulk reads
Use GET /v2/orders with x-session-id to list the orders owned by one session. A row is the same order summary the per-order read returns, minus customerState: a pause, an action, and a recovery are authoritative only on the per-order read. Bridge rows also carry asset and direction, so a list can label an XMR deposit against a TRX withdrawal without a read per row. Both are optional—swap rows omit them—so keep using product as the discriminator.
A row's status is derived by the rule above, but from a cheaper input: the list reads a progress projection refreshed shortly after each order event, while the per-order read watches the order's workflow live. A non-terminal projection that has gone unrefreshed for two minutes is treated as carrying no progress at all, and the row falls back to the order's stored status. A list row can therefore trail the per-order read—an order the detail already calls processing may briefly read awaiting_deposit in the list—and it never runs ahead. Treat the list as an index and the per-order read as the answer.
Refund address submission
PUT /v2/orders/{id}/refund-address is an ownership-protected action. It saves a refund address only when the order is eligible. For normal failed or expired orders, saving that address is not a completed refund. Continue tracking until status becomes refunded.
When refundRecovery.kind is wrong_chain, address submission only saves the immutable customer destination. Render the form only when customerState.action is refund_address; the recovery resource supplies its exact asset, chain, amount, and phase.
See actions and retries for owner-action eligibility and uncertain-request handling.