> ## 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.

# orderUpdates | Hyperliquid WebSocket API

> Hyperliquid orderUpdates: stream real-time order lifecycle events (placements, fills, cancels, and rejections) for one or more wallets on HyperCore.

<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%2Forder-updates).
</Tip>

<Info>
  * Wire-compatible with `wss://api.hyperliquid.xyz/ws` `orderUpdates` subscription - same channel name, same per-update shape.
  * Up to 1,000 wallet addresses per subscription. Use `addresses` (string\[]); aliases `user`(string) and `users` (string\[]) are also accepted.
  * Messages are batched per HyperCore block; each push carries one or more `updates` entries, each with its own `user` field. Subscribe many wallets and receive one push per block containing every matching wallet’s events.
  * Live-only — no historical snapshot of resting orders on subscribe. For the current resting-order set, use the Info API  <a href="https://goldrush.dev/docs/api-reference/hyperliquid-info/frontend-open-orders" target="_blank" rel="noopener noreferrer">`frontendOpenOrders`</a>. For historical fills, use <a href="https://goldrush.dev/docs/api-reference/hyperliquid-info/user-fills-by-time" target="_blank" rel="noopener noreferrer">`userFillsByTime`</a>.
  * No 1,000-subscription-per-IP cap. Multiplex many `orderUpdates` subscriptions on a single connection.
</Info>

Subscribe to one or more wallets and receive their live order status updates the moment they change when an order is placed, filled, canceled, or rejected. The server batches one push per HyperCore block, carrying every matching update as an `updates` array of objects, each tagged with the originating `user`.

**Supports up to 1,000 wallet addresses per subscription.**

## 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:

<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 `"orderUpdates"`.</ResponseField>

    <ResponseField name="addresses" type="string[]" required>
      One or more wallet addresses (lowercase `0x`-prefixed hex) to stream order updates for. Aliases `user` (string) and `users` (string\[]) are also accepted.
    </ResponseField>
  </Expandable>
</ParamField>

### Example

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

  > {"method":"subscribe","subscription":{"type":"orderUpdates","addresses":["0x010461c14e146ac35fe42271bdc1134ee31c703a"]}}
  ```

  ```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: "orderUpdates",
        addresses: ["0x010461c14e146ac35fe42271bdc1134ee31c703a"],
      },
    }));
  });

  ws.on("message", (raw) => {
    const msg = JSON.parse(raw.toString());
    if (msg.channel === "orderUpdates") {
      for (const update of msg.updates) {
        console.log(
          update.user,
          update.order.coin,
          update.order.side,
          update.order.sz,
          "@",
          update.order.limitPx,
          "->",
          update.status,
        );
      }
    }
  });
  ```

  ```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": "orderUpdates",
                  "addresses": ["0x010461c14e146ac35fe42271bdc1134ee31c703a"],
              },
          }))
          async for raw in ws:
              msg = json.loads(raw)
              if msg.get("channel") == "orderUpdates":
                  for update in msg["updates"]:
                      print(
                          update["user"],
                          update["order"]["coin"],
                          update["order"]["side"],
                          update["order"]["sz"],
                          "@",
                          update["order"]["limitPx"],
                          "->",
                          update["status"],
                      )

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

## Unsubscribe

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

```json theme={null}
{
  "method": "unsubscribe",
  "subscription": {
    "type": "orderUpdates",
    "addresses": ["0x010461c14e146ac35fe42271bdc1134ee31c703a"]
  }
}
```

<Note>
  Unsubscribe matches subscriptions by **exact body**. A subscription created with `addresses: ["0xAAA", "0xBBB"]` is a different subscription from two single-address subscriptions. To narrow the set, unsubscribe the original list in full, then resubscribe with the smaller list.
</Note>

## Streamed message

Each push has `channel: "orderUpdates"` and an `updates` array of objects - every order lifecycle event from the same HyperCore block that matches any subscribed wallet. Each entry is self-tagged with the originating `user`.

```json theme={null}
{
  "channel": "orderUpdates",
  "updates": [
    {
      "time": "2026-06-18T04:21:19.321641904",
      "user": "0x010461c14e146ac35fe42271bdc1134ee31c703a",
      "hash": "0xc2e340827d8e0749c45c043df991d1019b0058681881261b66abebd53c81e134",
      "status": "open",
      "builder": null,
      "order": {
        "coin": "W",
        "side": "B",
        "oid": 472501605004,
        "limitPx": "0.00963",
        "sz": "77502.4",
        "origSz": "77502.4",
        "timestamp": 1781756479321,
        "orderType": "Limit",
        "tif": "Alo",
        "reduceOnly": false,
        "isTrigger": false,
        "isPositionTpsl": false,
        "triggerCondition": "N/A",
        "triggerPx": "0.0",
        "cloid": null,
        "children": []
      }
    }
  ]
}
```

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

<ResponseField name="updates" type="object[]">
  Array of order lifecycle events from the same HyperCore block. Each entry carries its own `user` field, so a single push can contain events for multiple subscribed wallets.

  <Expandable title="update properties">
    <ResponseField name="time" type="string">ISO 8601 timestamp (nanosecond precision) of the HyperCore block in which the status transition occurred.</ResponseField>
    <ResponseField name="user" type="string">Wallet the update belongs to (lowercase `0x`-prefixed hex).</ResponseField>
    <ResponseField name="hash" type="string">Optional. L1 transaction hash for the action that produced this update. Present on placements (`"open"`); typically absent on terminal transitions like `"filled"` and `"canceled"`.</ResponseField>

    <ResponseField name="status" type="string">
      Order lifecycle state. Common values: `"open"`, `"filled"`, `"canceled"`, `"triggered"`, plus rejection codes (`"iocCancelRejected"`, `"selfTradeCanceled"`, `"badAloPxRejected"`, `"tickRejected"`, `"minTradeNtlRejected"`, `"reduceOnlyRejected"`, `"marginCanceled"`, `"vaultWithdrawalCanceled"`, `"openInsufficientMargin"`, `"perpMarginRejected"`, `"badTriggerPxRejected"`, `"marketOrderNoLiquidityRejected"`, `"positionIncreaseAtOpenInterestCapRejected"`, `"positionFlipAtOpenInterestCapRejected"`, `"tooAggressiveAtOpenInterestCapRejected"`, `"openInterestIncreaseRejected"`, `"insufficientSpotBalanceRejected"`, `"oracleNotFoundRejected"`, `"perpMaxPositionRejected"`).
    </ResponseField>

    <ResponseField name="builder" type="string | null">Builder address the order was routed through, or `null` if the order was not routed through a builder code.</ResponseField>

    <ResponseField name="order" type="object">
      Order snapshot at the moment of the status change.

      <Expandable title="order 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="side" type="string">`"B"` for buy/long, `"A"` for ask/short.</ResponseField>
        <ResponseField name="oid" type="int">Order ID.</ResponseField>
        <ResponseField name="limitPx" type="string">Limit price (decimal string).</ResponseField>
        <ResponseField name="sz" type="string">Current remaining size (decimal string). `"0.0"` after a full fill.</ResponseField>
        <ResponseField name="origSz" type="string">Original size at placement.</ResponseField>
        <ResponseField name="timestamp" type="int">Unix timestamp in milliseconds when the order was placed.</ResponseField>
        <ResponseField name="orderType" type="string">`"Limit"` or trigger variants (e.g. `"Stop Market"`, `"Stop Limit"`, `"Take Profit Market"`, `"Take Profit Limit"`).</ResponseField>
        <ResponseField name="tif" type="string">Time-in-force - `"Alo"` (add-liquidity-only / post-only), `"Ioc"` (immediate-or-cancel), or `"Gtc"` (good-til-cancel).</ResponseField>
        <ResponseField name="reduceOnly" type="boolean">`true` if the order is constrained to reduce an existing position.</ResponseField>
        <ResponseField name="isTrigger" type="boolean">`true` if this is a trigger (stop / take-profit) order.</ResponseField>
        <ResponseField name="isPositionTpsl" type="boolean">`true` for position-level take-profit / stop-loss orders.</ResponseField>
        <ResponseField name="triggerCondition" type="string">Human-readable trigger condition; `"N/A"` for plain limit orders.</ResponseField>
        <ResponseField name="triggerPx" type="string">Trigger price (decimal string); `"0.0"` for plain limit orders.</ResponseField>
        <ResponseField name="cloid" type="string | null">Optional client order ID (`0x`-prefixed 32-character hex) if one was set at placement, otherwise `null`.</ResponseField>
        <ResponseField name="children" type="object[]">Child orders (e.g. TP/SL attached at placement); empty array if none.</ResponseField>
      </Expandable>
    </ResponseField>
  </Expandable>
</ResponseField>

## Related endpoints

<CardGroup cols={2}>
  <Card title="userNonFundingLedgerUpdates" href="/api-reference/hyperliquid-websocket/user-non-funding-ledger-updates">stream real-time non-funding ledger events (deposits, withdrawals, vault and staking activity) for one or…</Card>
</CardGroup>

*Last reviewed: 2026-06-18*
