An order is created when the indexer sees a deposit carrying a known quote hash. Until then there is a quote but no order, and GetOrder returns the quote alone.

States

Same-chain swaps skip the middle entirely. The router performs the swap inside the deposit transaction, and the order goes to fulfilled once the finality indexer confirms it.

Collapsing states for a UI

Four outcomes are enough for most interfaces, and the SDK maps them for you:
failed covers refund_skipped, deposit_missing, refund_failed, and unsupported_deposit — the cases where a human needs to get involved. Everything not in the table above maps to pending.

Progress while pending

Two fields on the order carry real progress and are worth surfacing: Requirements vary by chain and by trade size, so render the ratio rather than a fixed count. Once src_confirmations reaches the requirement, the remaining wait is submission and destination confirmation, which is typically seconds.

Ambiguous outcomes

awaiting_refund_window is not a failure. It means a transaction reverted or was replaced and the operator refuses to guess what landed. After a quiet period both transaction hashes are re-polled and the order moves to whichever state matches the chain: fulfilled if the fulfillment actually landed, refunded if the refund did, or back into the refund path. Treat it as pending in a UI, and keep polling.
Never treat a destination transaction hash as proof of settlement. dst_tx_hash is populated when a transaction is submitted, not when it confirms. The order state is the authority.
See Track an order for polling patterns, and Refunds for what the refund branch pays out.