Trade History

GET/gateway/v1/hyperliquid/fills

Returns a wallet's individual fills (fill-level executions), newest first by default, with realized PnL, fees, and direction (`crossed`=true marks a taker fill that took liquidity). For closed round-trip trades (one row per open→close position, with per-trade P&L incl. funding), use `/hyperliquid/trades` instead — funding is NOT attributable at fill level.

Default `order=desc` is a recent-capped window (no `offset`): up to `limit` of the most-recent fills; page back by setting `to` to the oldest `time` you received (or `to_ms`+`to_fill_id` for millisecond-exact paging). For COMPLETE history with no cap, use `order=asc` with `from` and follow `meta.next_cursor`. `symbol` filters to one market (applied client-side, so with `order=desc` it only filters the recent window — pair with `from`/`to` to reach older history).

Query Parameters

addressstringrequired

Wallet address: a 0x EVM address or an ENS name (e.g. vitalik.eth). Solana addresses are not supported.

fromstring

Window start (Unix seconds or a date). With the default order=desc, results cover the window forward from this point and are capped at ~2000 of the earliest fills in range (narrow the range to see the most-recent fills). With order=asc this is the start of a complete-history walk: follow meta.next_cursor to page through every fill in the window with no cap.

Example: 2026-03-01
tostring

Window end (Unix seconds or a date), inclusive. Defaults to now. With order=desc, page back within the most-recent results by setting this to the oldest time you received (prefer to_ms for millisecond precision); with order=asc it bounds the walk.

Example: 2026-03-01
to_msinteger

Window end in Unix milliseconds, for millisecond-precise desc paging: pass the time_ms of the oldest fill you received to fetch the next page. On its own the boundary is exclusive (fills AT to_ms are dropped), so when more than limit fills share one millisecond the remainder is skipped — pair it with to_fill_id to page losslessly through a boundary millisecond. Takes precedence over to (which is ignored when to_ms is set). Like to, it pages within the recent (~2000-fill) window. desc-only: rejected with order=asc (use cursor instead).

to_fill_idstring

Cursor tiebreak for to_ms: pass the fill_id of the oldest fill you received alongside its time_ms as to_ms. The next page then resumes strictly after that (time_ms, fill_id) pair — fills at the boundary millisecond with a lower fill_id are included instead of skipped, so paging never loses fills that share a millisecond. Requires to_ms; desc-only. Equivalent to following meta.next_cursor, which encodes the same position. An empty page can mean the window is exhausted (set from to reach older history), not that no older fills exist.

orderenum<string>

desc (default): newest first — the recent feed, or the earliest-anchored ~2000-fill slice when from is set. asc: oldest first, a complete-history walk from from (required) up to to — each page links the next via meta.next_cursor with no result cap, the reliable mode for full trade-history or PnL reconstruction.

Available options:descasc
cursorstring

Opaque continuation token from a previous response's meta.next_cursor. It encodes the paging direction, position, and window, so pass it with only symbol and limit — combining it with from, to, to_ms, or to_fill_id is rejected with 400.

symbolstring

Filter to one market (exact match, e.g. xyz:GOLD). Applied client-side: with order=desc it filters after the recent cap (pair it with from/to so older fills are not missed); with order=asc the cursor walk scans past non-matching fills, so a page may return fewer than limit items (or none) while meta.next_cursor still advances.

limitinteger

Page size (1-100).

Trade History
const options = {method: 'GET'};

fetch('https://api.asksurf.ai/gateway/v1/hyperliquid/fills?from=2026-03-01&to=2026-03-01', options)
  .then(res => res.json())
  .then(res => console.log(res))
  .catch(err => console.error(err));
OK
{
  "$schema": "https://example.com/schemas/CursorDataResponseHyperliquidFill.json",
  "data": [
    {
      "closed_pnl": 123,
      "crossed": true,
      "direction": "<string>",
      "fee": 123,
      "fee_token": "<string>",
      "fill_id": "<string>",
      "hash": "<string>",
      "is_internal": true,
      "price": 123,
      "side": "<string>",
      "size": 123,
      "start_position": 123,
      "symbol": "<string>",
      "time": 123,
      "time_ms": 123,
      "tx_index": 123
    }
  ],
  "meta": {
    "cached": true,
    "credits_used": 123,
    "empty_reason": "<string>",
    "has_more": true,
    "limit": 123,
    "next_cursor": "<string>",
    "watermark": 123
  }
}