> ## 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.

# Trade history

> One list of your workspace's trades: the orders you placed and the trades on your exchange accounts, with filters and cursor paging.

`GET /api/v1/workspaces/{workspaceId}/trades` is your workspace's one trade history. It lists the orders placed through the API or the app and the trades on your connected exchange accounts together, newest first. Use it for reconciliation and reporting; to follow one order to the end, read it at its `statusUrl` instead ([Order status](https://tetrafi.mintlify.site/trade/order-status.md)).

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

The key needs **Read trades** ([Authentication](https://tetrafi.mintlify.site/authentication.md)). The path names your workspace: the `workspaceId` that `GET /api/v1/me` answers for your key. Another workspace answers `404 WORKSPACE_NOT_FOUND`.

## Read a page

Every row carries:

| Field | Meaning |
| - | - |
| `tradeId` | The trade's id. |
| `kind` | `order`, an order placed through TetraFi, or `venueTrade`, a trade on one of your exchange accounts. New kinds may be added: show one you do not recognise generically. |
| `projection` | The view the row was read through: `workspace` for an API key. |
| `createdAt` | When the trade was placed. |

The page also carries `total` (rows matching your filters), `limit` and `nextCursor`.

Filter with `kind` (`all`, `order` or `venueTrade`), `status`, and `from` and `to` (RFC 3339 times, placed at or after, at or before). `limit` sets the page size, 25 by default. Send `format=csv` for the same rows as CSV.

To read every row, pass `nextCursor` back as `cursor` with the same filters until it is `null`. An unknown parameter or value, or a filter the list cannot apply, answers `400 INVALID_REQUEST` naming the parameter.

```bash cURL theme={null}
# The path names your workspace: the workspaceId GET /api/v1/me answers for your key.
workspace=$TETRAFI_WORKSPACE_ID
# GET /api/v1/workspaces/{workspaceId}/trades lists the workspace's trades, newest first. Every row
# has tradeId, kind (order or venueTrade) and projection. Filter with kind, status, from and to;
# follow nextCursor until it is null. coverage lists kinds whose rows could not be read: the page
# is then partial, not shorter.
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)
page=$(tetrafi GET "/api/v1/workspaces/$workspace/trades?limit=5&from=$since")
jq -c '{total, nextCursor: (.nextCursor != null), coverage, excludedKinds}' <<<"$page" >&2
jq -c '.items[:3][] | {tradeId, kind, projection, createdAt}' <<<"$page" >&2
cursor=$(jq -r '.nextCursor // empty' <<<"$page")
if [[ -n $cursor ]]; then
  next=$(tetrafi GET "/api/v1/workspaces/$workspace/trades?limit=5&from=$since&cursor=$cursor")
  jq -c '{page: 2, rows: (.items | length)}' <<<"$next" >&2
fi
```

```json Output on test networks theme={null}
{"total":628,"nextCursor":true,"coverage":null,"excludedKinds":null}
{"tradeId":"9410e38e-…","kind":"venueTrade","projection":"workspace","createdAt":"2026-11-02T01:36:46.856947Z"}
{"tradeId":"3ba8fe03…","kind":"order","projection":"workspace","createdAt":"2026-11-01T23:51:28Z"}
{"tradeId":"de0a1b4b-…","kind":"venueTrade","projection":"workspace","createdAt":"2026-11-01T22:55:48.448012Z"}
{"page":2,"rows":5}
```

## Read one trade

`GET /api/v1/workspaces/{workspaceId}/trades/{tradeId}` reads one row of the list through the same view, with its detail. An order's `settlement` says how it ended:

| Field | Meaning |
| - | - |
| `settlement.status` | `pending`, `settled`, `failed`, `refunded` or `unknown`. New values may be added: treat one you do not recognise as `unknown`. |
| `settlement.failureReason` | A sentence saying why, when `status` is `failed` or `refunded`. `null` otherwise. Show it to a person; branch on `status`, never on this text. |

An unknown `tradeId`, or one from another workspace, answers `404`.

```bash cURL theme={null}
# GET …/trades/{tradeId} reads one trade through the same view. An order's settlement says how it
# ended: status pending, settled, failed, refunded or unknown, and failureReason, a sentence
# saying why, when it failed or was refunded.
failed=$(tetrafi GET "/api/v1/workspaces/$workspace/trades?kind=order&status=failed&limit=1")
trade_id=$(jq -r '.items[0].tradeId // empty' <<<"$failed")
if [[ -z $trade_id ]]; then
  trade_id=$(tetrafi GET "/api/v1/workspaces/$workspace/trades?kind=order&limit=1" | jq -r '.items[0].tradeId // empty')
fi
if [[ -n $trade_id ]]; then
  trade=$(tetrafi GET "/api/v1/workspaces/$workspace/trades/$trade_id")
  jq -c '{tradeId, kind, settlement: (.settlement | if . == null then null else {status, failureReason} end)}' <<<"$trade" >&2
fi
```

```json Output on test networks theme={null}
{"tradeId":"673828c6…","kind":"order","settlement":{"status":"failed","failureReason":"Profitability validation failed: Bad Request: Accepted output differs from the priced post-fill payload"}}
```

## When a page is partial

Two fields say when the list holds less than it could:

* `coverage` lists each kind whose rows could not be read just now, with its `state`. The page shows the other kinds and is partial, not shorter: read it again later rather than treating the missing rows as absent.
* `excludedKinds` lists each kind a filter or sort left out, with the `filter` it could not apply. Drop that filter to see the kind again.

A `503 TRADE_PROJECTION_UNAVAILABLE` means the trade history cannot be read on this deployment right now. Retry later.

## Exchange account balances

What your exchange accounts hold, and the deposits their venues credited, are read with the same key: see [Exchange account balances](https://tetrafi.mintlify.site/trade/venue-balances.md).


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