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

# List user trades

> Read finalized maker and taker trades with allocated fees and PnL.

<Info>Response JSON below is an illustrative testnet snapshot, not a live mainnet result. Use the selected server and its network-specific addresses for actual requests.</Info>

<ParamField path="userId" type="string" required>
  Unsigned decimal Kuru user ID.
</ParamField>

<ParamField query="limit" type="integer" default="100">
  Page size from `1` through `500`.
</ParamField>

<ParamField query="cursor" type="string">
  Opaque exclusive continuation cursor from `pagination.nextCursor`.
</ParamField>

<ParamField query="marketAddress" type="string">
  Optional lowercase 20-byte market filter for trade rows only. It does not filter `data.positions`.
</ParamField>

<ParamField query="from" type="integer">
  Inclusive Unix time in seconds.
</ParamField>

<ParamField query="to" type="integer">
  Inclusive Unix time in seconds. When both bounds are present, `to` must be
  greater than `from`.
</ParamField>

<ResponseField name="feedEpoch" type="integer | null" required>
  Feed epoch containing `globalUserSeq`.
</ResponseField>

<ResponseField name="globalUserSeq" type="string | null" required>
  Finalized user sequence covered by the materialized response.
</ResponseField>

<ResponseField name="data" type="object" required>
  Trade history and the complete position baseline.

  <Expandable title="Data fields">
    <ResponseField name="trades" type="array" required>
      Maker and taker user legs ordered newest first by canonical source position.
    </ResponseField>

    <ResponseField name="trades[].tradeId" type="string" required />

    <ResponseField name="trades[].recordIdx" type="integer" required />

    <ResponseField name="trades[].marketAddress" type="string" required />

    <ResponseField name="trades[].symbol" type="string" required />

    <ResponseField name="trades[].isMaker" type="boolean" required />

    <ResponseField name="trades[].isBuy" type="boolean" required>
      Side of this user leg.
    </ResponseField>

    <ResponseField name="trades[].liquidity" type="string" required>
      `active` for active FIFO liquidity or `passive` for passive-band liquidity.
    </ResponseField>

    <ResponseField name="trades[].price" type="string" required>
      Execution price in market price precision (pp).
    </ResponseField>

    <ResponseField name="trades[].filledSize" type="string" required>
      Fill quantity in the market's native size precision.
    </ResponseField>

    <ResponseField name="trades[].updatedSize" type="string" required>
      Remaining active-order or passive-liquidity size after the fill.
    </ResponseField>

    <ResponseField name="trades[].fees" type="object" required>
      Actual allocated fee amounts. Every value is normalized to x18 using integer
      floor division.
    </ResponseField>

    <ResponseField name="trades[].pnl" type="object" required>
      Per-fill realized PnL and the available post-trade cost-basis cut.
    </ResponseField>

    <ResponseField name="trades[].blockTimestamp" type="integer" required>
      Block proposal time in Unix seconds.
    </ResponseField>

    <ResponseField name="trades[].blockNumber" type="string" required />

    <ResponseField name="trades[].transactionHash" type="string" required />

    <ResponseField name="positions" type="array" required>
      Position baseline across all tracked markets for this user, ordered by market
      address. Independent of trade pagination, market filters, and time filters.
      Includes tracked closed positions with zero size and cost; returns `[]` when
      there are no tracked positions. These are trade-accounting positions, not token balances.

      <Expandable title="Position fields">
        <ResponseField name="marketAddress" type="string" required>
          Lowercase market address.
        </ResponseField>

        <ResponseField name="openSize" type="string" required>
          Open base inventory in native market size precision (sp).
        </ResponseField>

        <ResponseField name="openCost" type="string" required>
          Cost basis of that inventory in native quote-token units. Divide by
          `10^quoteTokenDecimals` for display, using the market's quote token metadata.
        </ResponseField>
      </Expandable>
    </ResponseField>
  </Expandable>
</ResponseField>

<ResponseField name="pagination.nextCursor" type="string | null" required />

The fee fields are `makerFee`, `takerFee`, `builderFeeBase`, and
`builderFeeQuote`. Inapplicable amounts are zero. These are allocated fee
amounts, not PPS rates.

The PnL fields are `grossRealizedPnl`, `realizedPnl`, `openSize`, and
`openCost`. Realized PnL fields remain x18; `openCost` uses native quote-token
units and `openSize` uses native market size precision. This matches the units
of `data.positions[].openCost` and `data.positions[].openSize`. `openSize` and `openCost` are `null` when the row does not publish
an authoritative post-trade position cut.

On the first page, `data.positions` and the replay cursor describe the same committed
state, after complete trade matches. Historical `data.trades[].pnl` values still describe
their individual trades, not this current baseline. Continuation pages retain
the first page's positions and replay cursor, even when newer trades arrive.

When both cursor fields are non-null, install `data.positions` once as the accounting
baseline and subscribe to `userTrades@f`, using `feedEpoch` and passing
`globalUserSeq` as the subscription's `seq`. Do not overwrite live positions
when loading additional history pages. A fresh first-page request establishes
a new baseline. If either cursor field is null, the response cannot establish
a replay handoff; do not interpret a missing cursor as zero.

The example below illustrates the response shape; cursor values are opaque.

<ResponseExample>
  ```json 200 theme={null}
  {
    "feedEpoch": 18,
    "globalUserSeq": null,
    "data": {
      "trades": [
        {
          "tradeId": "101",
          "recordIdx": 1,
          "marketAddress": "0x0a082280e4ea3d822e23ec1186685477241a039d",
          "symbol": "WETHUSDC",
          "isMaker": true,
          "isBuy": false,
          "liquidity": "active",
          "price": "24707100",
          "filledSize": "60000000",
          "updatedSize": "940000000",
          "fees": {
            "makerFee": "0",
            "takerFee": "0",
            "builderFeeBase": "0",
            "builderFeeQuote": "0"
          },
          "pnl": {
            "grossRealizedPnl": "-327912000000000000",
            "realizedPnl": "-327912000000000000",
            "openSize": "260000000",
            "openCost": "65640954"
          },
          "blockTimestamp": 1788353771,
          "blockNumber": "59066947",
          "transactionHash": "0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
        },
        {
          "tradeId": "98",
          "recordIdx": 0,
          "marketAddress": "0x0a082280e4ea3d822e23ec1186685477241a039d",
          "symbol": "WETHUSDC",
          "isMaker": true,
          "isBuy": true,
          "liquidity": "active",
          "price": "25227200",
          "filledSize": "80000000",
          "updatedSize": "920000000",
          "fees": {
            "makerFee": "0",
            "takerFee": "0",
            "builderFeeBase": "0",
            "builderFeeQuote": "0"
          },
          "pnl": {
            "grossRealizedPnl": "0",
            "realizedPnl": "0",
            "openSize": "320000000",
            "openCost": "80788866"
          },
          "blockTimestamp": 1788342297,
          "blockNumber": "59028992",
          "transactionHash": "0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
        },
        {
          "tradeId": "97",
          "recordIdx": 0,
          "marketAddress": "0x0a082280e4ea3d822e23ec1186685477241a039d",
          "symbol": "WETHUSDC",
          "isMaker": true,
          "isBuy": false,
          "liquidity": "active",
          "price": "25277700",
          "filledSize": "80000000",
          "updatedSize": "920000000",
          "fees": {
            "makerFee": "0",
            "takerFee": "0",
            "builderFeeBase": "0",
            "builderFeeQuote": "0"
          },
          "pnl": {
            "grossRealizedPnl": "19736000000000000",
            "realizedPnl": "19736000000000000",
            "openSize": "240000000",
            "openCost": "60600794"
          },
          "blockTimestamp": 1788342296,
          "blockNumber": "59028988",
          "transactionHash": "0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
        },
        {
          "tradeId": "96",
          "recordIdx": 0,
          "marketAddress": "0x0a082280e4ea3d822e23ec1186685477241a039d",
          "symbol": "WETHUSDC",
          "isMaker": true,
          "isBuy": true,
          "liquidity": "active",
          "price": "25566900",
          "filledSize": "80000000",
          "updatedSize": "920000000",
          "fees": {
            "makerFee": "0",
            "takerFee": "0",
            "builderFeeBase": "0",
            "builderFeeQuote": "0"
          },
          "pnl": {
            "grossRealizedPnl": "0",
            "realizedPnl": "0",
            "openSize": "320000000",
            "openCost": "80801058"
          },
          "blockTimestamp": 1788342288,
          "blockNumber": "59028961",
          "transactionHash": "0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
        },
        {
          "tradeId": "95",
          "recordIdx": 0,
          "marketAddress": "0x0a082280e4ea3d822e23ec1186685477241a039d",
          "symbol": "WETHUSDC",
          "isMaker": true,
          "isBuy": false,
          "liquidity": "active",
          "price": "25618000",
          "filledSize": "80000000",
          "updatedSize": "920000000",
          "fees": {
            "makerFee": "0",
            "takerFee": "0",
            "builderFeeBase": "0",
            "builderFeeQuote": "0"
          },
          "pnl": {
            "grossRealizedPnl": "375708000000000000",
            "realizedPnl": "375708000000000000",
            "openSize": "240000000",
            "openCost": "60342878"
          },
          "blockTimestamp": 1788342287,
          "blockNumber": "59028956",
          "transactionHash": "0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
        }
      ],
      "positions": [
        {
          "marketAddress": "0x0a082280e4ea3d822e23ec1186685477241a039d",
          "openSize": "260000000",
          "openCost": "65640954"
        }
      ]
    },
    "pagination": {
      "nextCursor": "eyJ2IjoxLCJyIjoidXNlci10cmFkZXMiLCJmIjoiYzJmNThiMGRjNDQyOWQ1MjBlYzczZDgyNzRjN2I1NDUzYmViODk3NDRkMTQ3YzVmOTRiMjkzYzY0YzJkZjYxNiIsInMiOiJlZWIzM2I0ZTFmYjMyNTZmNzc5YWYxOTEwMjU5ZDE4YzQzYjliNjc5ZWQ4MzIzOTQ1MWM0ZGU5ZmMwZTkwYjg4IiwibyI6MCwiZSI6MTc4ODQzNDA0OH0.cJ6grTznYNiRPhNs2QZq3ErEyxuc7g9A9i2RTj6FmRg"
    }
  }
  ```
</ResponseExample>


## OpenAPI

````yaml api/data-source/openapi.yaml GET /api/v1/users/{userId}/trades
openapi: 3.1.0
info:
  title: Kuru Data Source API
  version: 1.0.0
servers:
  - url: https://api.mainnet.kuru.io
    description: Monad mainnet (default)
  - url: https://api.testnet.kuru.io
    description: Monad testnet
security: []
paths:
  /api/v1/users/{userId}/trades:
    get:
      summary: Get user trades
      operationId: getUserTrades
      parameters:
        - name: userId
          in: path
          required: true
          schema:
            type: integer
        - name: marketAddress
          in: query
          schema:
            type: string
        - name: limit
          in: query
          schema:
            type: integer
        - name: cursor
          in: query
          schema:
            type: string
        - name: from
          in: query
          schema:
            type: integer
        - name: to
          in: query
          schema:
            type: integer
      responses:
        '200':
          description: User trades

````

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