> ## Documentation Index
> Fetch the complete documentation index at: https://tetrafi.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Order status

> Follow an order to the end: one read for every order, what each status means, when it is final, and how often to poll.

`POST /api/v1/orders` answers as soon as the order is accepted. To follow it to the end, read it at the `statusUrl` the answer gives: `GET /api/v1/orders/{id}`. The read answers the same envelope as the order answer, for Basic and Advanced orders alike, so one parser reads both.

> [!NOTE]
>
> The API may change until launch. Every change is listed in the [Changelog](https://tetrafi.mintlify.site/changelog.md).

If you lost the order answer, [recover the order by its quote](https://tetrafi.mintlify.site/trade/idempotency.md#recover-an-order-by-its-quote): it returns the same `statusUrl`. The key needs **Read orders**. Any member or key of the order's workspace with that permission can read it, not only the one that placed it. An order that does not exist, or that belongs to another workspace, answers `404 ORDER_NOT_FOUND`.

## The envelope

| Field | Meaning |
| - | - |
| `orderId` | The order's id: the one `GET /api/v1/orders/{id}` takes. |
| `kind` | `basicTrade`, a trade TetraFi executes for you on a venue, or `advancedTrade`, an on-chain order. |
| `status` | Where the order is (below). |
| `terminal` | `true` when the order can no longer change. Stop polling on this, not on a particular `status`. |
| `next` | Present only while there is something to do in the meantime (below). |
| `statusUrl` | Where to read the order again. |
| `quoteId` | The quote it was placed from, when known. |
| `operation` or `order` | The venue trade's or on-chain order's own detail, for `basicTrade` or `advancedTrade`. |

## Statuses

| `status` | What it means | Final |
| - | - | - |
| `pending` | Accepted; nothing has been sent to a venue yet. | No |
| `working` | Sent to the venue and executing, including an on-chain trade waiting for its transaction to confirm. | No |
| `filled` | Executed; settlement or delivery is still to complete. | No |
| `settled` | Executed and settled, or there was nothing to settle. | Yes |
| `unfilled` | The venue did not fill it, or it was never sent, for example because the wallet refused to sign (`operation.dispatch.notSentCause` says why). Nothing was traded. | Yes |
| `refused` | A pre-trade check refused it before anything was sent. `operation.complianceRefusal` names why. The order is final: to trade once the cause is cleared, request a new quote and place a new order. | Yes |
| `cancelled` | Cancelled before it was sent. | Yes |
| `failed` | Refused or failed; nothing more will happen. | Yes |
| `refunded` | Your funds were returned. | Yes |
| `reviewRequired` | A person must review it before it can continue, such as a compliance hold. | No |
| `outcomeUnknown` | TetraFi lost track of the outcome, for example a trade whose settlement was not seen in time. It is being reconciled, and the trade may have filled. | No |

An order can skip statuses: act on `terminal`, not on a particular sequence. More values may be added: treat one you do not recognise as "other" and keep following `terminal`.

When an order ends `failed` or `refunded`, read it in the trade history to see why: its `settlement.failureReason` is a sentence for a person ([Read one trade](https://tetrafi.mintlify.site/trade/trade-history.md#read-one-trade)).

> [!WARNING]
>
> `outcomeUnknown` is not a failure. The trade may have filled. Never place a new order for it: keep reading its status.

## While it is not final

`next` says what to do while the order is not final:

| `next.kind` | What to do |
| - | - |
| `wait` | Read it again after `retryAfter`, an ISO 8601 duration such as `PT15S`. TetraFi is reconciling the outcome. |
| `contact` | Contact support with `reference`. A person has to look at the order. |

Without `next`, poll every 10 to 15 seconds until `terminal` is `true`.

```bash cURL theme={null}
# Read the order at the statusUrl its answer gave: the same envelope as POST /orders, for
# Basic and Advanced orders alike. Poll every 10 to 15 seconds until terminal is true. While it
# is not, next can say what to do: wait (retryAfter) or contact support with its reference.
# A status you do not recognise is "other": keep following terminal.
status_url=$(jq -r '.statusUrl' <<<"$placed")
for _ in $(seq 1 12); do
  read_order=$(tetrafi GET "$status_url")
  jq -c '{kind, status, terminal, next}' <<<"$read_order" >&2
  [[ $(jq -r '.terminal' <<<"$read_order") == true ]] && break
  wait=$(jq -r '.next | select(.kind == "wait") | .retryAfter | capture("^PT(?<s>[0-9]+)S$").s' \
    <<<"$read_order" 2>/dev/null || true)
  sleep "${wait:-10}"
done
```

```json Output on test networks theme={null}
{"kind":"basicTrade","status":"settled","terminal":true,"next":null}
```

## What the order did

Every order also says what it actually did, in the same keys on Basic and Advanced orders. These are recorded facts, never the quote carried forward.

| Field | Meaning |
| - | - |
| `fills` | Each confirmed fill, in execution order: `amount` (what it delivered), `sellAmount`, `price`, `at`, `venue`, and `txHash` with its `network` for an on-chain fill. Empty until a fill is confirmed. A field that was not recorded is `null`. |
| `quotedBuyAmount` | What the executed quote said would land. `null` when it is not known, for example before a venue order is sent. |
| `settledBuyAmount` | What actually landed, read from the fills or the settlement. `null` until it is measured. Compare it with `quotedBuyAmount` to see what the trade delivered against its quote. |
| `fees` | Each fee actually charged: `kind`, `amount`, `asset`, `chain` for an on-chain charge, and `includedInPrice`. When `includedInPrice` is `true`, the venue took the fee inside its price: the fill amounts already reflect it, so it is not charged on top. |
| `unrecordedFees` | The kinds of fee the order incurred whose amount is not recorded, for example a venue fee taken inside the price without an amount. Show these as "not recorded", never as 0. A kind that is in neither list was not charged. |
| `settlesBy` | The latest time the order settles, or can no longer execute, under its recorded terms. `null` when no deadline is recorded: an off-chain Basic trade on an exchange account, or a same-chain DEX swap, whose call carries no deadline. |

A fee's `kind` is `trading` (the venue's fee), `relayer`, `forwarding`, `transfer`, `network` (gas the order's wallet paid) or `platform` (the TetraFi fee). New kinds may be added: show one you do not recognise generically.

```bash cURL theme={null}
# Every order also says what it actually did, on Basic and Advanced orders alike. settledBuyAmount
# is null until it is measured, never the quote carried forward. A fee whose amount was not
# reported is left out of fees and its kind listed in unrecordedFees: show it as not recorded,
# never as 0. settlesBy is null when no deadline is recorded, for example a same-chain DEX swap.
filled=""
for status in settled filled; do
  [[ -n $filled ]] || filled=$(tetrafi GET "/api/v1/orders?limit=1&from=$since&status=$status" | jq -r '.items[0].orderId // empty')
done
if [[ -n $filled ]]; then
  filled=$(tetrafi GET "/api/v1/orders/$filled")
  jq -c '{orderId, kind, quotedBuyAmount, settledBuyAmount, fills: [.fills[] | {amount, at, network}],
    fees: [.fees[] | {kind, amount, asset, includedInPrice}], unrecordedFees, settlesBy}' <<<"$filled" >&2
fi
```

```json Output on test networks theme={null}
{"orderId":"9410e38e-…","kind":"basicTrade","quotedBuyAmount":"0.499751","settledBuyAmount":"0.499751","fills":[{"amount":"0.499751","at":"2026-11-02T01:37:12Z","network":"eip155:11155111"}],"fees":[{"kind":"relayer","amount":"0.000249","asset":"USDC","includedInPrice":false},{"kind":"network","amount":"0.000000332622","asset":"ETH","includedInPrice":false},{"kind":"network","amount":"0.000000438318","asset":"ETH","includedInPrice":false},{"kind":"platform","amount":"0.000049","asset":"USDC","includedInPrice":false}],"unrecordedFees":[],"settlesBy":null}
```

## List your orders

`GET /api/v1/orders` lists your workspace's orders, newest first, each in the same envelope as `GET /api/v1/orders/{id}`. The key needs **Read orders**.

| Query parameter | What it filters |
| - | - |
| `status` | One status from the list above. |
| `kind` | `basicTrade` or `advancedTrade`. |
| `sellAsset`, `buyAsset` | The asset paid or received, such as `USDC`. |
| `from`, `to` | Created at or after, and at or before, an RFC 3339 time. |
| `limit` | Up to 20 orders a page; 20 when left out. |
| `cursor` | The previous page's `nextCursor`. |

A page with a `status` filter keeps reading until it has `limit` orders or your orders end, up to a limit on how many orders it examines. When it stops at that limit, the page can hold fewer than `limit` orders, even none, with `scanLimitReached: true` and a `nextCursor`: more orders remain to examine. A filter that matches nothing answers one page with `nextCursor` `null`. Either way, keep following `nextCursor` until it is `null`. A cursor belongs to the key and the exact filters it came with; any other answers `400 INVALID_CURSOR`. The script [`samples/http/orders-list.sh`](https://github.com/tetrafi/docs/blob/main/samples/http/orders-list.sh) lists the last 30 days:

```bash cURL theme={null}
# GET /api/v1/orders lists your workspace's orders, newest first, in the same envelope as
# GET /api/v1/orders/{id}. Filter by status, kind, sellAsset, buyAsset and a from/to time range.
# A page can hold fewer than limit items, even none: follow nextCursor until it is null.
since=$(date -u -v-30d +%Y-%m-%dT%H:%M:%SZ 2>/dev/null || date -u -d '30 days ago' +%Y-%m-%dT%H:%M:%SZ)
orders=() pages=0 cursor=""
while (( pages < 5 )); do
  page=$(tetrafi GET "/api/v1/orders?limit=20&from=$since${cursor:+&cursor=$cursor}")
  pages=$((pages + 1))
  while IFS= read -r line; do orders+=("$line"); done < <(jq -c '.items[] | {orderId, kind, status, terminal}' <<<"$page")
  cursor=$(jq -r '.nextCursor // empty' <<<"$page")
  [[ -z $cursor ]] && break
done
echo "orders: ${#orders[@]} across $pages pages" >&2
printf '%s\n' "${orders[@]:0:3}" >&2
```

```json Output on test networks (shortened) theme={null}
orders: 100 across 5 pages
{"orderId":"b7670e34-…","kind":"basicTrade","status":"unfilled","terminal":true}
{"orderId":"dad901ac-…","kind":"basicTrade","status":"settled","terminal":true}
```

## In the app

The same trade appears under **Trades**, with its status.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.