The hub answers “where is my order?” three different ways, because it’s really three different questions. This page lays out all three: which id opens which view, how one order moves through them over time, and when to stop polling each one.

The three status views

None of the three supersedes another — they answer from different sources, and a client following an order to completion typically reads more than one.

Which id opens which view

The full id-namespace table and how each id derives from the others is Conventions — the three order-id namespaces — not restated here. One gap worth calling out explicitly: the Permit2 (EVM escrow-gasless) lane discloses no on-chain id anywhere in the quote. The id appears at submission, not on observation: the openFor ack’s orderId is the on-chain id on this lane, and the order’s GET /orders entry carries it as onchainOrderId at once, before any chain object, with onchainOrderIdSource: "upstream" — the aggregator’s answer, which the hub does not recompute on this lane (the lanes it recomputes read "verified").

One order over time

A gasless openFor order, followed end to end:
  1. POST /order/openfor acks with upstream state: "created".
  2. Until the Open is observed, GET /orders’ entry has no chain object at all — chain is a fact about what has been observed, not a placeholder that starts in some default state (it would only read AWAITING_OPEN if a fill were somehow observed before the Open). Once the escrow’s Open is observed on the source chain, chain.status reads OPEN.
  3. The upstream reports executing then executed, with a fillTransaction reference — unverified at this point.
  4. The destination fill is observed on chain; chain.status becomes FILLED.
  5. The on-chain view shows settled once the settle is observed (gated by attestation — an observed settle is the attesters’ approval, made visible). The upstream may report settled and then finalized, skip settled, or stop at executed for good (known issue).
  6. finalized on the upstream view, SETTLED on the chain view — both terminal, from different sources. The upstream’s settled is not terminal: finalized can follow it.
Each view lags by a different amount: the two status-route caches are 2 seconds; the on-chain observer watermarks lag by however long the observers take to ingest a block; a chain’s GET /status/{orderId} watermark moves only when the reconciler processes a new observation on that chain, so on a quiet chain it can be far behind (known issue).

Following an order

  • openFor orders: GET /order/{orderId}/status every 2–3 s until finalized, failed or refunded, with a stall rule: an order can stay executed long after it filled and settled on chain. Once it is executed, read GET /onchain/{orderId}/fill by its onchainOrderId, and hand off to it after a few minutes without progress (known issue).
  • open-flow orders: GET /status/{orderId}, with your key or your project id.
  • your organization’s history: GET /orders — the openFor orders placed under the X-Infinity-Subject you send: one user’s, or everyone’s when all your calls share one subject; open-flow registrations are not listed — then the on-chain views by onchainOrderId.
  • from a web page with your project id: every view above but the history. Keep the ids of the orders the page submits, and follow them on the status routes and the on-chain views; GET /orders needs your server’s key (Authentication — project ids).

Advisory versus observed

The upstream view is explicitly advisory, on its own terms: stateSource is always "upstream-advisory", finalityVerified is always false, and upstreamFillReported records only that the upstream supplied a fill reference — it is not chain proof. Treat every field on that view as “what the aggregator says”, never as settled fact. Show money — a fill actually happening, funds actually moving — from the on-chain views only.

Terminal states per view

See also