> For the complete documentation index, see [llms.txt](https://docs.hydromancer.xyz/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.hydromancer.xyz/readme/websocket/builderliquidations.md).

# builderLiquidations

Note: TWAP fills do not carry builder codes. If a user's last fill before liquidation was a TWAP fill, no builder liquidation notification will be sent.

{% hint style="info" %}
💧New endpoint - this endpoint is not a part of original Hyperliquid API and is added by us for builder convenience.
{% endhint %}

### Subscribe

```json
{ 
  "type": "subscribe", 
  "subscription": { 
    "type": "builderLiquidations", 
    "builder": "0x..", // your builder address
    "aggregateByTime": true
  }
}

```

### Parameters

<table><thead><tr><th>Parameter</th><th width="117.7105712890625">Type</th><th width="118.0491943359375">Required</th><th width="108.1435546875">Default</th><th>Description</th></tr></thead><tbody><tr><td>builder</td><td>string</td><td>Yes</td><td>-</td><td>Your builder address</td></tr><tr><td>dex</td><td>string</td><td>No</td><td>null</td><td>Filter by DEX: "xyz", "main" ( for fills only on first dex)</td></tr><tr><td>aggregateByTime</td><td>boolean</td><td>No</td><td>true</td><td>Aggregate multi-fill liquidations by (user, time, order_id)</td></tr></tbody></table>

### Unsubscribe

**note: make sure to use exactly the same message as subscription message.**

```json
{ 
  "type": "unsubscribe", 
  "subscription": { 
    "type": "builderLiquidations", 
    "builder": "0x..",
    "aggregateByTime": true
  } 
}
```

### Liquidation data format

{% hint style="info" %}
**Reconnection Note:** When reconnecting with a session, replay and live events may overlap. Deduplicate using `(time, txIndex)` - skip liquidation fills where this tuple is at or before your last processed fill. See [Session Management](/readme/websocket/session-management-and-reconnection.md#deduplication) for details.
{% endhint %}

Each message contains an array of liquidation fills. Each fill is a tuple of \[user\_address, fill\_data].

```json
{ 
  "type": "builderLiquidations", 
  "seq": 1,
  "cursor": "500:1704067200000:3",
  "liquidations": [ 
    [ 
      "0x742d35cc6634c0532925a3b844bc9e7595f7f2e2", 
      { 
        "coin": "ETH", 
        "px": "2150.50", 
        "sz": "1.5", 
        "side": "A", 
        "time": 1704067200000, 
        "startPosition": "1.5", 
        "dir": "Close Long", 
        "closedPnl": "-125.50", 
        "hash": "0xabc...def", 
        "oid": 12345678, 
        "crossed": true, 
        "fee": "2.50", 
        "tid": 87654321, 
        "cloid": null, 
        "builderFee": null,
        "deployerFee": null,
        "feeToken": "USDC",
        "builder": "0x..", // my builder address
        "twapId": null, 
        "txIndex": 1, 
        "liquidation": { 
          "liquidatedUser": "0x742d35cc6634c0532925a3b844bc9e7595f7f2e2", 
          "markPx": "2148.00", 
          "method": "market"
         }, 
         "user": "0x742d35cc6634c0532925a3b844bc9e7595f7f2e2" 
       } 
     ] 
   ] 
 }
```

### Examples

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

```javascript
const WebSocket = require('ws');

const ws = new WebSocket(`wss://api.hydromancer.xyz/ws?token=${process.env.HYDROMANCER_API_KEY}`);

ws.on('message', (data) => {
    const msg = JSON.parse(data);

    if (msg.type === 'connected') {
        // Subscribe to builder liquidations
        ws.send(JSON.stringify({
            type: 'subscribe',
            subscription: {
                type: 'builderLiquidations',
                builder: 'YOUR_BUILDER_CODE'
            }
        }));
    } else if (msg.type === 'ping') {
        ws.send(JSON.stringify({ type: 'pong' }));
    } else if (msg.type === 'builderLiquidations') {
        console.log(`Received ${msg.liquidations.length} liquidation fills`);
        for (const [user, fill] of msg.liquidations) {
            console.log(`User ${user} liquidated: ${fill.sz} ${fill.coin} @ ${fill.px}`);
            if (fill.liquidation) {
                console.log(`  Liquidated user: ${fill.liquidation.liquidatedUser}`);
                console.log(`  Mark price: ${fill.liquidation.markPx}`);
            }
        }
    }
});
```

{% endtab %}

{% tab title="Python" %}

```python
import websocket
import json
import os

def on_message(ws, message):
    msg = json.loads(message)

    if msg['type'] == 'connected':
        ws.send(json.dumps({
            'type': 'subscribe',
            'subscription': {
                'type': 'builderLiquidations',
                'builder': 'YOUR_BUILDER_CODE'
            }
        }))
    elif msg['type'] == 'ping':
        ws.send(json.dumps({'type': 'pong'}))
    elif msg['type'] == 'builderLiquidations':
        print(f"Received {len(msg['liquidations'])} liquidation fills")
        for user, fill in msg['liquidations']:
            print(f"User {user}: {fill['sz']} {fill['coin']} @ {fill['px']}")

ws = websocket.WebSocketApp(
    f"wss://api.hydromancer.xyz/ws?token={os.environ['HYDROMANCER_API_KEY']}",
    on_message=on_message
)
ws.run_forever()
```

{% endtab %}
{% endtabs %}

#### Error messages:

```
{
    "type": "error",
    "message": "Invalid API key"
}
```

#### Common errors

1. ```
   Connection timeout - Respond to ping messages
   ```
2. ```
   Too many subscriptions - Maximum builder subscriptions per API key
   ```
3. ```
   Invalid builder code
   ```
4. ```
   Invalid API key
   ```
