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

> ## Agent Instructions
> To integrate AGG, start with Quickstart: REST (https://docs.agg.market/quickstart/rest), then Order lifecycle & statuses (https://docs.agg.market/concepts/order-lifecycle).
> Track every trade until it reaches a terminal status. Before retrying a failed or timed-out call, read Errors, retries & idempotency (https://docs.agg.market/concepts/errors).
> The API reference is generated from https://docs.agg.market/openapi/openapi.json.

# Order lifecycle & statuses

> Every order status, which ones are final, and how to track a trade to a final state

Trading calls return `pending` right away and finish in the background. You find out how a trade
ended by polling, or by listening for webhooks and WebSocket events. Always keep going until you
reach a terminal state.

## Two levels of status

| Level | Where | Values |
| - | - | - |
| Trade | `overallState` on `GET /execution/status` | One state for the whole quote, across all its orders |
| Order | `status` on each order | One status per venue order |

A fill split across two venues is one trade with two orders.

## Order statuses

| Status | Terminal | Meaning |
| - | - | - |
| `pending` | No | Accepted. Funds are being checked. |
| `signing` | No | The order is being signed. |
| `pending_bridge` | No | Funds are moving to the venue's chain. |
| `submitting` | No | Being sent to the venue. |
| `submitted` | No | Sent to the venue, waiting for confirmation. |
| `open` | No | A limit order resting on the venue's book. |
| `partially_filled_open` | No | A resting limit order with some fills and size left. |
| `cancel_pending` | No | Cancel requested, waiting for the venue to confirm. |
| `filled` | **Yes** | Fully filled. |
| `partial_fill` | **Yes** | Part filled. The rest will not fill. See `partialFillReason`. |
| `failed` | **Yes** | Failed. See `errorMessage` or `errorReason`. |
| `expired` | **Yes** | Timed out, or a limit order reached its expiry. |
| `cancelled` | **Yes** | Cancelled by the user or the system. |

A market order never shows `open`, `partially_filled_open`, or `cancel_pending`.

`partialFillReason` is an open set. Known values: `venue_capacity`, `price_slipped`,
`venue_cancelled`, `venue_expired`, `venue_closed`, `user_cancelled`, `timeout`,
`clearinghouse_capacity`, `native_remainder_voided`.

```mermaid theme={null}
stateDiagram-v2
    [*] --> pending
    pending --> signing
    pending --> pending_bridge
    pending --> submitting
    signing --> submitting
    pending_bridge --> submitting
    submitting --> submitted
    submitted --> filled
    submitted --> partial_fill
    submitted --> open: limit order
    open --> partially_filled_open
    open --> cancel_pending
    partially_filled_open --> cancel_pending
    open --> filled
    partially_filled_open --> filled
    partially_filled_open --> partial_fill
    cancel_pending --> cancelled
    cancel_pending --> filled
    pending --> failed
    submitting --> failed
    submitted --> failed
    pending_bridge --> expired
    open --> expired
    pending --> cancelled
    filled --> [*]
    partial_fill --> [*]
    failed --> [*]
    expired --> [*]
    cancelled --> [*]
```

The diagram shows the usual paths. Not every order visits every state, and a failure can happen
from any in-flight state. Branch on the status you read, not on the path you expect.

## Trade states

`GET /execution/status` rolls the orders up into `overallState`:

| `overallState` | Terminal | Meaning |
| - | - | - |
| `created` | No | Accepted, execution has not started. |
| `routing`, `quoting`, `placing`, `confirming` | No | In progress. |
| `filled` | Yes | Every order filled. |
| `partially_filled` | Yes | At least one order filled or part filled, and at least one did not fill in full. |
| `cancelled` | Yes | Every order was cancelled. |
| `expired` | Yes | Every order expired. |
| `failed` | Yes | Anything else that ended without a fill. |

Stop when `terminal` is `true`, not when you see a particular state. `terminal` can stay `false`
for a short time after every order is final, while steps that run after the fill finish.

## Poll a quote-based trade

Use this for `POST /execution/fill`, and for `POST /execution/orders` using the `quoteId` in its
response.

<CodeGroup>
  ```bash cURL theme={null}
  curl -G https://api.agg.market/execution/status \
    -H "x-app-id: $AGG_APP_ID" \
    -H "Authorization: Bearer $ACCESS_TOKEN" \
    --data-urlencode "quoteId=$QUOTE_ID"
  ```

  ```ts SDK theme={null}
  let status = await client.getExecutionStatus({ quoteId });
  while (!status.terminal) {
    await new Promise((r) => setTimeout(r, status.pollAfterMs ?? 1000));
    status = await client.getExecutionStatus({ quoteId });
  }
  console.log(status.overallState, status.orders);
  ```
</CodeGroup>

Key fields in the response:

| Field | Meaning |
| - | - |
| `terminal` | `true` once nothing will change. Stop polling. |
| `overallState` | The trade state above. |
| `pollAfterMs` | Wait this long before the next poll. `null` when terminal. |
| `orders[]` | Per order: `orderId`, `venue`, `status`, `filledAmountRaw`, `actualSharesRaw`, `executionPriceRaw`, `txHash`, `errorReason`. |
| `steps[]` | Progress rows for a UI. Group by `groupId` and show `label`. |
| `errorReason` | Why the trade failed, when it did. |
| `pendingSignatures[]` | Self-custody only: requests the user's wallet must sign. |

`404` means no order is recorded for that `quoteId` for this user yet. Right after a fill request,
the request may still be running, so a `404` is not proof that the fill was rejected. See
[safe retries](/concepts/errors#idempotency-and-safe-retries). Raw amounts are strings in 6-decimal units: `"15300000"` is \$15.30 or 15.3 shares.

API reference: [Get execution status](/api-reference/trading/get-execution-status).

## Poll by order id or your own id

`GET /execution/orders` lists the user's orders. Filter it to one order:

| Filter | Use for |
| - | - |
| `orderId` | Limit orders, cancels, and any order you hold the id of |
| `externalId` | A direct order after a timeout, when you never saw the response |
| `quoteId` | Every leg of a quote |
| `status`, `orderType`, `venueMarketIds` | Lists and reconciliation |

```bash theme={null}
curl -G https://api.agg.market/execution/orders \
  -H "x-app-id: $AGG_APP_ID" \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  --data-urlencode "orderId=$ORDER_ID"
```

Each row has `status`, `filledAmountRaw`, `actualSharesRaw`, `executionPrice`, `txHash`, and
`errorMessage`. Poll until `status` is terminal. A resting limit order stays `open` until it fills,
is cancelled, or expires.

## Push instead of polling

| Channel | Events | Notes |
| - | - | - |
| [Webhooks](/recipes/webhooks/overview) | `trades.placed`, `trades.filled` | Server-to-server. `trades.filled` carries `status` `filled` or `partial_fill`, and your `externalId` for direct orders. There is no webhook for a failed trade, so poll to catch failures. |
| [WebSocket](/recipes/websocket-notifications) | `order_event` | For a signed-in user in the browser. Use REST to backfill on page load and reconnect. |

Payloads are small. Read the order from the API for amounts and prices.

## Idempotency at a glance

| Call | Safe to retry? |
| - | - |
| `POST /execution/orders` | Yes, with the same `externalId`. A repeat returns `409` instead of a second trade. |
| `POST /execution/limit-orders` | Yes, with the same `clientOrderId`. A repeat for the same user returns `409`. |
| `POST /execution/fill` | A `quoteId` fills at most once. After a timeout, poll status for that `quoteId` before doing anything else. |
| `POST /execution/withdraw` | Yes, with the same `requestId`. |

Full rules: [Errors, retries & idempotency](/concepts/errors).
