Declined before anything was opened
The full per-code rows are on Submit order (openFor) — Errors — not
restated here.
Refused after the transaction was sent
On the proxy lanes (oif-wrap-native, oif-swap-token) the user’s own transaction opens the order
in escrow before POST /order/openfor registers it, so a refusal there
comes after the deposit:
A new quote would mean a second deposit. The deposit completes on chain anyway — the solver still
fills it — but the hub never records the order, so it is missing from
GET /orders and the status routes
(known issue). Follow it by the send transaction’s hash on
GET /onchain/tx/{chainDomain}/{txHash}/order, then
GET /onchain/{orderId}/fill, and withdraw after the escrow expires if it is
not filled (Refunds).
The open flow is the same: POST /order comes after the user sent
executionTx, so none of its refusals (EIN0005 past expiresAt, EIN0006, EIN0007, EIN0010)
is a reason to re-quote — the transaction already sent completes on chain anyway, unregistered.
The upstream’s failure report
failed and refunded are reachable from any non-terminal upstream state — a fill attempt can
fail at any point in its life, not just at the start. failedAt names the upstream’s transaction
stage at which the attempt failed, one of: Prepare, Fill, PostFill, PreClaim, Claim. The
hub gives no meaning for each stage beyond its name — treat the list as an enum to display, not a
set of causes to explain.
failureReason is the upstream’s own text — display it, never parse it; the hub does not
normalize it into a code. history[] lists the states the hub read on the way there, which is not
always the full path: a state passed between two reads is absent. Once state reaches failed or
refunded, stop polling — see Order lifecycle.
Reports the hub refuses
The upstream’s own report of an order’s state isn’t taken at face value:rejectedUpstreamTransition: true— the latest report was backwards, unknown, or contradicted the accepted state, so the hub kept the previous one instead.upstreamStale: true— the accepted state couldn’t be refreshed on the last attempt; the last good state is still served.EIN0007with no earlier state — the hub has nothing to fall back to when an upstream answer is refused this early.
What the chain says
GET /orders’ chain.status can read EXPIRED (render it as a failure) or REFUNDED — both
from the chain’s own facts rather than the upstream’s report. REFUNDED is terminal; EXPIRED is
not: no fill can complete the order any more, but once its refund is observed the entry reads
REFUNDED, so keep reading it. What happens to a proxy-lane deposit whose registration was
refused: Refunds.