Skip to content
Guides

Track orders

GET /v2/orders/{orderId} is public: anyone holding the orderId can read the order without a key. It allows any origin, so a browser can poll it directly. Keep order ids out of shared URLs, logs and analytics.

Poll every 10 to 15 seconds until state is delivered or delivery_failed. There are no webhooks. Keep polling through withdrawn_on_hub, which means hub settlement with delivery not yet fully recorded. Use a local timeout and retain the orderId to resume: a timeout means the result is unconfirmed, not that the transfer failed. See Order lifecycle for every state and cases where delivery tracking can remain incomplete.

Nested objects are null until their event is seen, so “not yet” is distinct from “seen, with zero”. Every at is unix seconds.

Field What it tells you
state Where the order is.
deposit The deposit seen on the source chain. Stays null on a non-EVM source.
traces.withdraw The settlement on the hub: settledOutcome paid out (destination units), refundSource refunded and accruedFee kept (source units).
deliver The payout and refund transfers as they land: deliver.payout on the destination chain, deliver.refund on the source chain.
deliveryFailed Set with delivery_failed: which transfer could not be delivered.
traces.rootIntentId The published intent. You need it to sign a cancel.
traces.chainObservations The intent’s trail on the hub: one entry per fill with intentState: "Solved", plus one "Cancelled" entry for a cancellation or expiry. A Cancelled entry whose at is before the deadline was a cancel.

Two timing details:

  • traces.withdraw appears as soon as the order settles, but its amounts can be null for a short time until the settlement event is indexed. traces.withdraw present with settledOutcome: null means “settled, amounts still coming”. Poll again.
  • deliver.*.amount repeats the figures in traces.withdraw. It is not measured from the transfer itself.

The API’s delivered state covers both payouts and refunds. When the state is delivered:

  • deliver.payout alone means a payout was delivered.
  • deliver.refund alone means the order was refunded, after fees. Show Refunded to the user.
  • Both mean a partial fill paid out and the remainder was refunded.

refunded is a display label here, not a separate v2 API state. A refund is complete only after its source-chain transfer is recorded; withdrawn_on_hub alone is not enough.

Some figures are not returned:

  • No endpoint returns the filled source amount or the commission earned on one order. settledOutcome divided by the rate recovers the filled source only approximately.
  • fullFee is everything held back at publish, your commission included. On a partial fill Khalani keeps only part of it, and accruedFee reports that part. It includes the whole flat fee, so it is non-zero whenever the pair has a flat fee, even on an order that never filled.
  • Your commission reaches your commission wallet as its own transfer on the hub.

Responses carry no build timestamp and no nonce. Record the build time yourself.

Addresses come back lowercase in orders and checksummed from /v2/params and /v2/quote. Compare them case-insensitively.

GET /v2/orders returns your orders, newest first by build time, always limited to your key’s account.

Query Meaning
depositor, from, to Filter by depositor or by source or destination token. Either form of a TRON address matches.
state One of the eight states.
limit Page size, 1 to 200. Default 50.
cursor nextCursor from the previous page.

Entries have the same shape as a single order, except that traces.chainObservations is always empty: read the single order for its trail.

Terminal window
curl -s "https://api.hyperstream.dev/v2/orders?state=published&limit=20" -H "X-API-Key: $KHALANI_API_KEY"

Paging rules:

  • The cursor marks a position. Orders built after your first page do not appear on later pages. To pick up new orders, poll the first page.
  • Keep the filters unchanged while paging.
  • A final, partial page still carries a cursor. Stop when a page comes back with no orders.
  • There is no time filter, and unknown query parameters are ignored, not rejected. For a recurring job, read from the first page until you reach an orderId you already have.