# userCompletedTradesByTime

Returns completed trades for a user with `close_time` ≥ `startTime` (or after a `cursor`), ordered **oldest-first** by `close_time` then `tx_index`. Pagination is identical to [`userFillsByTime`](/readme/rest-api/historical-data/userfillsbytime.md): pass `startTime` for the first page, then on each subsequent page pass the `cursor` `"{close_time}_{tx_index}"` built from the **last record** of the previous response. When `cursor` is supplied, `startTime` is ignored and the boundary record is excluded from the next page (no duplicates, no `+ 1` hack).

`dex` is optional. Omit to return trades from every perp DEX. Set to `"main_dex"` for the native Hyperliquid dex, or to a HIP-3 dex name (e.g. `"xyz"`) to scope the trade list to that dex.

**note: completed-trade data starts from 1st of aug 2025**

## POST Request

<table><thead><tr><th width="161.9998779296875">Field</th><th width="119">Type</th><th>Description</th></tr></thead><tbody><tr><td><code>type</code></td><td>string</td><td>Must be <code>"userCompletedTradesByTime"</code></td></tr><tr><td><code>user</code></td><td>string</td><td>Ethereum address (0x-prefixed, 42 characters)</td></tr><tr><td><code>startTime</code></td><td>integer</td><td>Earliest <code>close_time</code> to include (Unix ms, inclusive). Skipped when <code>cursor</code> is used. Either <code>startTime</code> or <code>cursor</code> must be supplied</td></tr><tr><td><code>endTime</code></td><td>integer</td><td>Latest <code>close_time</code> to include (Unix ms, inclusive). Default: now (optional)</td></tr><tr><td><code>cursor</code></td><td>string</td><td>Composite of <code>close_time</code> and <code>tx_index</code> with <code>"_"</code> separator (e.g. <code>"1734571490123_12"</code>). Take from the <strong>last record</strong> of the previous response (optional)</td></tr><tr><td><code>limit</code></td><td>integer</td><td>Max results to return. Default 100, max 500 (optional)</td></tr><tr><td><code>dex</code></td><td>string</td><td>Scope to a single perp DEX. <code>"main_dex"</code> for the native Hyperliquid dex, or a HIP-3 dex name (e.g. <code>"xyz"</code>). Omit for all dexes (optional)</td></tr></tbody></table>

{% tabs %}
{% tab title="cURL" %}

```bash
# First page
curl -X POST https://api.hydromancer.xyz/info \
  -H "Authorization: Bearer $HYDROMANCER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "type": "userCompletedTradesByTime",
    "user": "0x0000000000000000000000000000000000000000",
    "startTime": 0,
    "limit": 100
  }'

# Next page — cursor built from the last record of the previous response
curl -X POST https://api.hydromancer.xyz/info \
  -H "Authorization: Bearer $HYDROMANCER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "type": "userCompletedTradesByTime",
    "user": "0x0000000000000000000000000000000000000000",
    "cursor": "1734571490123_12",
    "limit": 100
  }'
```

{% endtab %}

{% tab title="Python" %}

```python
import requests
import os

url = 'https://api.hydromancer.xyz/info'
headers = {
    'Authorization': f'Bearer {os.environ.get("HYDROMANCER_API_KEY")}',
    'Content-Type': 'application/json',
}
user = '0x0000000000000000000000000000000000000000'
limit = 500

params = {'type': 'userCompletedTradesByTime', 'user': user, 'startTime': 0, 'limit': limit}
while True:
    page = requests.post(url, json=params, headers=headers).json()
    if not page:
        break
    for trade in page:
        ...  # process trade
    if len(page) < limit:
        break
    last = page[-1]
    params = {
        'type': 'userCompletedTradesByTime',
        'user': user,
        'cursor': f"{last['close_time']}_{last['tx_index']}",
        'limit': limit,
    }
```

{% endtab %}

{% tab title="Javascript" %}

```javascript
import axios from 'axios';

const url = 'https://api.hydromancer.xyz/info';
const headers = {
    'Authorization': `Bearer ${process.env.HYDROMANCER_API_KEY}`,
    'Content-Type': 'application/json',
};
const user = '0x0000000000000000000000000000000000000000';
const limit = 500;

let params = { type: 'userCompletedTradesByTime', user, startTime: 0, limit };
while (true) {
    const { data: page } = await axios.post(url, params, { headers });
    if (!page.length) break;
    for (const trade of page) { /* process trade */ }
    if (page.length < limit) break;
    const last = page[page.length - 1];
    params = {
        type: 'userCompletedTradesByTime',
        user,
        cursor: `${last.close_time}_${last.tx_index}`,
        limit,
    };
}
```

{% endtab %}
{% endtabs %}

***

## Response Fields

JSON array of completed-trade records, ordered **oldest-first** by `close_time` then `tx_index`. Same record shape as [userCompletedTrades](/readme/rest-api/user-performance/usercompletedtrades.md):

| Field                  | Type     | Description                                                                               |
| ---------------------- | -------- | ----------------------------------------------------------------------------------------- |
| `user`                 | string   | Ethereum address                                                                          |
| `coin`                 | string   | Asset symbol                                                                              |
| `position_type`        | string   | `"Long"` or `"Short"`                                                                     |
| `gross_pnl`            | string   | Realized PnL before fees                                                                  |
| `net_pnl`              | string   | Realized PnL after fees and funding (`gross_pnl - fees + funding_pnl`)                    |
| `funding_pnl`          | string   | Cumulative funding PnL accrued while the position was open. Already included in `net_pnl` |
| `entry_px`             | string   | Volume-weighted average entry price                                                       |
| `exit_px`              | string   | Volume-weighted average exit price                                                        |
| `position_closed_size` | string   | Size of the closed position, in contracts                                                 |
| `fees`                 | string   | Total fees paid on fills attributed to this position                                      |
| `fills`                | int      | Number of fills on this position                                                          |
| `maker_fills`          | int      | Number of uncrossed (maker) fills on this position                                        |
| `open_time`            | int      | Time the position was opened (Unix ms)                                                    |
| `close_time`           | int      | Time the position was fully closed (Unix ms) — **first half of the next-page `cursor`**   |
| `duration_ms`          | int      | `close_time - open_time` in milliseconds                                                  |
| `max_position_size`    | string   | Peak absolute position size during the position's lifetime                                |
| `builder`              | string?  | Builder address from the closing fill, if any                                             |
| `tx_index`             | int      | Transaction index of the closing fill — **second half of the next-page `cursor`**         |
| `leverage`             | int?     | Leverage at close. `null` if predates leverage tracking                                   |
| `is_cross`             | boolean? | `true` = cross margin, `false` = isolated. `null` when `leverage` is null                 |


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.hydromancer.xyz/readme/rest-api/user-performance/usercompletedtradesbytime.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
