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

# builderFills | Hyperliquid WebSocket API

> Hyperliquid builderFills: stream live attributed fills for one or more builder addresses in real time.

<CardGroup cols={2}>
  <Card title="Credit Cost"> 1 per minute</Card>
  <Card title="Processing"> Realtime</Card>
</CardGroup>

<Tip>
  Estimate your monthly cost for this API using the [Pricing Calculator](/pricing-calculator?endpoint=%2Fapi-reference%2Fhyperliquid-websocket%2Fbuilder-fills).
</Tip>

<Info>
  * GoldRush-native: No `wss://api.hyperliquid.xyz/ws` equivalent.
  * Pass `builder` (string) for a single builder or `addresses` (string\[]) for many. `aggregateByTime` optional.
  * Live-only: No historical snapshot on subscribe. For windowed history, use the Info API <a href="https://goldrush.dev/docs/api-reference/hyperliquid-info/builder-fills-by-time" target="_blank" rel="noopener noreferrer">`builderFillsByTime`</a>.
  * Same per-fill shape as `userFills`, plus `builder` and `builderFee` on every entry; channel name in messages is `builderFills`.
</Info>

Subscribe to one builder address (`builder`) or many (`addresses`) and receive every fill routed through those builders as they execute, batched per block as `[address, fill]` tuples. Each fill carries the matched `builder` address and the corresponding `builderFee`.

## Endpoint

```
wss://hypercore.goldrushdata.com/ws?key=<GOLDRUSH_API_KEY>
```

<ParamField query="key" type="string" required>
  Your GoldRush API key. Passed as a query parameter at connection time - no `Authorization` header is used.
</ParamField>

## Subscribe

Send this JSON message after the connection is established. Provide either `builder` (single address) or `addresses` (array of addresses).

<ParamField body="method" type="string" required>
  Always `"subscribe"`.
</ParamField>

<ParamField body="subscription" type="object" required>
  <Expandable title="properties">
    <ResponseField name="type" type="string" required>Always `"builderFills"`.</ResponseField>

    <ResponseField name="builder" type="string">
      Single builder address (lowercase `0x`-prefixed 42-character hex) to stream fills for. Mutually exclusive with `addresses`.
    </ResponseField>

    <ResponseField name="addresses" type="string[]">
      Array of builder addresses to stream fills for - the multi-builder form of `builder`. Mutually exclusive with `builder`.
    </ResponseField>

    <ResponseField name="aggregateByTime" type="boolean">
      When `true`, partial fills of the same order within the same block are merged into one. Default `false`.
    </ResponseField>
  </Expandable>
</ParamField>

### Example

<CodeGroup>
  ```bash wscat theme={null}
  wscat -c "wss://hypercore.goldrushdata.com/ws?key=$GOLDRUSH_API_KEY"

  > {"method":"subscribe","subscription":{"type":"builderFills","builder":"0xb84168cf3be63c6b8dad05ff5d755e97432ff80b"}}
  ```

  ```typescript TypeScript theme={null}
  import WebSocket from "ws";

  const ws = new WebSocket(
    `wss://hypercore.goldrushdata.com/ws?key=${process.env.GOLDRUSH_API_KEY}`,
  );

  ws.on("open", () => {
    ws.send(JSON.stringify({
      method: "subscribe",
      subscription: {
        type: "builderFills",
        builder: "0xb84168cf3be63c6b8dad05ff5d755e97432ff80b",
      },
    }));
  });

  ws.on("message", (raw) => {
    const msg = JSON.parse(raw.toString());
    if (msg.channel === "builderFills") {
      for (const [address, fill] of msg.fills) {
        console.log(address, fill.coin, fill.side, fill.sz, "@", fill.px, "builderFee:", fill.builderFee);
      }
    }
  });
  ```

  ```python Python theme={null}
  import asyncio, json, os
  import websockets

  async def main():
      uri = f"wss://hypercore.goldrushdata.com/ws?key={os.environ['GOLDRUSH_API_KEY']}"
      async with websockets.connect(uri) as ws:
          await ws.send(json.dumps({
              "method": "subscribe",
              "subscription": {
                  "type": "builderFills",
                  "builder": "0xb84168cf3be63c6b8dad05ff5d755e97432ff80b",
              },
          }))
          async for raw in ws:
              msg = json.loads(raw)
              if msg.get("channel") == "builderFills":
                  for address, fill in msg["fills"]:
                      print(address, fill["coin"], fill["side"], fill["sz"], "@", fill["px"], "builderFee:", fill.get("builderFee"))

  asyncio.run(main())
  ```
</CodeGroup>

## Unsubscribe

Send the same `subscription` body with `method: "unsubscribe"`:

```json theme={null}
{
  "method": "unsubscribe",
  "subscription": {
    "type": "builderFills",
    "builder": "0xb84168cf3be63c6b8dad05ff5d755e97432ff80b"
  }
}
```

<Note>
  Unsubscribe matches subscriptions by **exact body**. A subscription created with `builder: "0xAAA"` is a different subscription from one created with `addresses: ["0xAAA"]`, even if they target the same builder. To narrow a multi-builder set, unsubscribe the original list in full, then resubscribe with the smaller list.
</Note>

## Streamed message

Each push has `channel: "builderFills"` and a `fills` array of `[address, fill]` tuples. The first element of each tuple is the trader who executed the fill; the `fill` object carries the trade details, including the `builder` it was routed through and the `builderFee` earned.

```json theme={null}
{
  "channel": "builderFills",
  "fills": [
    [
      "0x742d35cc6634c0532925a3b844bc9e7595f7f2e2",
      {
        "coin": "ETH",
        "px": "2150.5",
        "sz": "1.5",
        "side": "B",
        "time": 1704067200000,
        "startPosition": "1.5",
        "dir": "Open Long",
        "closedPnl": "125.5",
        "hash": "0xabc...def",
        "oid": 12345678,
        "crossed": false,
        "fee": "2.5",
        "tid": 87654321,
        "feeToken": "USDC",
        "twapId": null,
        "builderFee": "0.1",
        "builder": "0xb84168cf3be63c6b8dad05ff5d755e97432ff80b"
      }
    ]
  ]
}
```

<ResponseField name="channel" type="string">Always `"builderFills"`.</ResponseField>

<ResponseField name="fills" type="array<[string, object]>">
  Tuples of `[address, fill]`. The `address` is the trader who placed the order; the `fill` object carries the trade details plus builder-attribution fields.

  <Expandable title="fill properties">
    <ResponseField name="coin" type="string">Asset symbol - e.g. `"BTC"`, `"ETH"` for perps; spot pairs use the `@N` form (e.g. `"@107"`).</ResponseField>
    <ResponseField name="px" type="string">Fill execution price (decimal string).</ResponseField>
    <ResponseField name="sz" type="string">Fill size (decimal string).</ResponseField>
    <ResponseField name="side" type="string">`"B"` for buy/long, `"A"` for ask/short.</ResponseField>
    <ResponseField name="time" type="int">Unix timestamp in milliseconds when the fill executed.</ResponseField>
    <ResponseField name="startPosition" type="string">Signed position size the trader held on this coin immediately before this fill.</ResponseField>
    <ResponseField name="dir" type="string">Human-readable direction label - `"Open Long"`, `"Open Short"`, `"Close Long"`, `"Close Short"`, `"Buy"`, `"Sell"`, or position-flip labels `"Long > Short"` / `"Short > Long"`.</ResponseField>
    <ResponseField name="closedPnl" type="string">Realized PnL in USDC attributable to this fill for the trader (zero when the fill opens or extends a position).</ResponseField>
    <ResponseField name="hash" type="string">L1 transaction hash that included this fill.</ResponseField>
    <ResponseField name="oid" type="int">Parent order ID.</ResponseField>
    <ResponseField name="crossed" type="boolean">`true` when the fill came from the taker side of the order, `false` when it was the maker side.</ResponseField>
    <ResponseField name="fee" type="string">Trading fee paid by the trader for this fill, denominated in `feeToken`.</ResponseField>
    <ResponseField name="tid" type="int">Unique trade ID.</ResponseField>
    <ResponseField name="feeToken" type="string">Symbol the fee was paid in - typically `"USDC"`.</ResponseField>
    <ResponseField name="twapId" type="int | null">Parent TWAP order ID if this fill is a slice of a TWAP, otherwise `null`.</ResponseField>
    <ResponseField name="builder" type="string">Builder address the order was routed through - matches one of the subscribed builders.</ResponseField>
    <ResponseField name="builderFee" type="string">Builder fee earned for this fill, denominated in `feeToken`.</ResponseField>
    <ResponseField name="cloid" type="string">Optional. Client order ID (`0x`-prefixed 32-character hex) if one was set at order placement.</ResponseField>

    <ResponseField name="liquidation" type="object">
      Optional. Present only when this fill closed a position as part of a liquidation event.

      <Expandable title="properties">
        <ResponseField name="liquidatedUser" type="string">The wallet whose position was liquidated.</ResponseField>
        <ResponseField name="markPx" type="string">Mark price at the time of liquidation.</ResponseField>
        <ResponseField name="method" type="string">Liquidation method - `"market"` or `"backstop"`.</ResponseField>
      </Expandable>
    </ResponseField>
  </Expandable>
</ResponseField>

## Errors

A missing or malformed `builder`/`addresses` field returns an error message on the same channel:

```json theme={null}
{ "channel": "error", "data": "subscription builderFills requires a 'builder' field" }
```

## Related endpoints

<CardGroup cols={2}>
  <Card title="allFills" href="/api-reference/hyperliquid-websocket/all-fills">stream every fill on HyperCore in real time for global market analytics and cross-wallet order-flow…</Card>
  <Card title="liquidationFills" href="/api-reference/hyperliquid-websocket/liquidation-fills">stream a global, market-wide feed of every liquidation fill on HyperCore.</Card>
  <Card title="userFills" href="/api-reference/hyperliquid-websocket/user-fills">stream real-time trade fills for one or more wallets as they execute on HyperCore.</Card>
</CardGroup>

*Last reviewed: 2026-06-19*
