> The index of these docs, for agents: https://traktor.fun/llms.txt

# Trades

The trade row field by field, and the flags and caveats that qualify a row or a whole answer.

A trade is one token bought or sold in a swap Traktor decoded on a tracked chain, credited to the app that routed it.

## A trade row

The stream sends each trade as a row in an `events` frame's `d`, `origin: "live"` rows alone.

```json
{
  "id": "bnb:0x7f3a9c1e5d2b4a6f8e0c1d3b5a7f9e2c4d6b8a0f1e3c5d7b9a2f4e6c8d0b1a3c:0",
  "chain": "bnb",
  "platform": "fomo",
  "blockTime": "2026-10-03T12:00:00.000Z",
  "blockTimeSource": "interpolated",
  "blockTimeErrorSeconds": null,
  "height": 63012345,
  "blockHash": "0x04fbf4984c35b45017775d90548fbc1a065c0ce57d8e9cd2fe5cf495b1b1786a",
  "finality": "confirmed",
  "wallet": "0x1111111111111111111111111111111111111111",
  "tokenAddress": "0x2222222222222222222222222222222222222222",
  "side": "buy",
  "tokenAmount": 125000,
  "usdAmount": 412.5,
  "priceUsd": 0.0033,
  "ingestedAt": "2026-10-03T12:00:01.870Z",
  "lagSeconds": 1.9,
  "origin": "live",
  "flags": ["blocktime_interpolated"]
}
```

| Field | Meaning |
| --- | --- |
| `id` | `chain:tx:leg`, or `chain:tx:<app>:leg:side:token` for a Coinbase Wallet or Bankr trade (`app` is `coinbase` or `bankr`): `tx` is the transaction hash, or the signature on Solana, and `leg` the trade's place in it, since one transaction can hold several trades. Deduplicate on it. |
| `chain`, `platform` | The chain, and the app that routed the trade. [The flow filter](https://traktor.fun/docs/filters.md#flow-filter) lists the names each takes. |
| `blockTime` | When the trade's block was produced. |
| `blockTimeSource` | `chain` on Solana, Coinbase Wallet and Bankr rows, whose time is read from the block. `interpolated` on every other row: treat its time as placed between known blocks. |
| `blockTimeErrorSeconds` | Always `null`: the error of an interpolated time is not measured per row. |
| `height` | The block number, or the slot on Solana. |
| `blockHash` | The block's hash on EVM rows; `null` on Solana rows. |
| `finality` | `confirmed` on a row stored without proof that its block is final: every EVM row, and a Solana row read before its slot finalized. Every other row is `null`. A Solana row stays if its slot is later abandoned. |
| `wallet` | The trader's own wallet, not the router's. |
| `tokenAddress` | The token bought or sold. |
| `side` | `buy` when the trader bought the token, `sell` when they sold it. |
| `tokenAmount` | Tokens traded, decimals applied. |
| `usdAmount` | The trade's value in USD, or `null` when none was measured. |
| `priceUsd` | USD per token at this trade, `usdAmount` over `tokenAmount`, or `null` when not measured. |
| `ingestedAt` | When Traktor stored the row. The stream nearly runs in this order, but a row that commits late can follow rows stored after it. |
| `lagSeconds` | `ingestedAt` minus `blockTime`, in seconds to a tenth. It is never clamped: when an interpolated block time runs ahead, it reads negative. |
| `origin` | `live` on every row the stream sends. A row Traktor recovers later by rereading earlier blocks is stored as `sweep` or `backfill`, and never reaches the stream. |
| `flags` | What qualifies this row: [Flags](#flags). |

## Null is not zero

`usdAmount: null` means no USD value was measured, not that the trade was free, and `priceUsd` is `null` with it. A `null` `usdAmount` satisfies no bound: `minUsd` and `maxUsd` both leave the row out, and the answer says so with `usd_amount_nullable`.

## Flags

`flags` qualifies one row, and is empty when nothing does.

| Flag | Meaning |
| --- | --- |
| `usd_missing` | The trade has no USD value: `usdAmount` is null. |
| `price_unknown` | No price was measured for the token: `priceUsd` is null. |
| `blocktime_interpolated` | This chain and app can have its block times placed between known blocks rather than read, so treat `blockTime` as approximate; `blockTimeSource` says `interpolated`. |
| `late_arrival` | The row arrived more than 120 seconds after its block time. |
| `rbh_buy_understated` | A buy on the Robinhood chain, other than through Coinbase Wallet or Bankr: its notional reads about 8% low, systematically, and is stated, never corrected. |

## Caveats

`meta.caveats` qualifies a whole REST answer, and is empty when nothing does.

| Caveat | Meaning |
| --- | --- |
| `data_stale` | A chain-and-app pair on a chain the answer covers has stopped arriving, possibly an app the filter leaves out; `coverage` in `GET /v1/alert-capabilities` says which. |
| `coverage_gap` | A chain the filter names has no tracked app, or an app it names is tracked on no chain, so that name matches no trade. Sent today only for `elysium`, which is in the vocabulary while no app is read there. |
| `coverage_unread` | Whether each chain and app is still arriving could not be read just now, so the answer's other caveats come from the last reading; until it is read again, `coverage` in `GET /v1/alert-capabilities` is `available: false`. |
| `provider_discovered_partial` | The scope includes a pair whose coverage is partial: its row in `coverage` in `GET /v1/alert-capabilities` reads `coverage: "partial"`, and its `coverageNote` says what that pair's trades leave out. |
| `scan_capped` | The request examined its row budget before it filled the page; the page may be short and `hasMore` is true. |
| `usd_amount_nullable` | A USD bound is set, so rows with no USD value are left out. |

The stream's `ack` carries warnings of its own, listed with its [frames](https://traktor.fun/docs/stream.md#frames).

## Late rows

Rows are not stored in block-time order. A row can be stored long after its block, as `lagSeconds` and `late_arrival` show, and a row stored later can carry an earlier block time than the one before it. The stream therefore follows arrival, not block time, and `blockTime` cannot mark your place in it: resume from a `seq` ([Resume](https://traktor.fun/docs/stream.md#resume)). [`maxLagSeconds`](https://traktor.fun/docs/filters.md#flow-filter) sets how late a row may arrive and still match.

## Retention

Trades are kept `retention.flowsHours` hours past their block time: `GET /v1/meta/filters` publishes the figure, and [Coverage](https://traktor.fun/docs/filters.md#coverage) shows it.

A market answer holding a view that reads trades carries `meta.retention`: `horizonHours`, the hours kept; `floorAt`, the earliest block time kept when the answer was built; and `truncated`, `true` when the window reaches back past that floor.
