Real-time fill feed for authenticated users.
This channel provides per-account trade data with realized PnL, similar to the REST /v1/trade-history endpoint but in real-time.
Authentication Required: Yes - This channel requires authentication and automatically filters fills to the authenticated account.
Subscribe
{
"method": "subscribe",
"params": {
"channel": "fills",
"market_ids": [1, 2]
}
}| Parameter | Type | Required | Description |
|---|---|---|---|
market_ids | number[] | No | Filter by market IDs. Empty = all markets |
Note: The account is automatically determined from the authenticated session. You cannot subscribe to fills for other accounts.
Authentication
Before subscribing to the fills channel, you must authenticate:
{
"method": "auth",
"params": {
"account": "0x1234567890123456789012345678901234567890",
"signer": "0xabcdefabcdefabcdefabcdefabcdefabcdefabcd",
"message": "WebSocket Authentication",
"nonce": 1703123456,
"signature": "0x..."
}
}Message Format
Update
Sent immediately when a trade occurs where you are either the maker or taker. There is no snapshot for this channel - historical fills are available via the REST API.
{
"channel": "fills",
"type": "update",
"market_id": "1",
"data": {
"id": "318622-318647",
"market_id": "1",
"order_id": "318622",
"side": "BUY",
"price": "92995",
"size": "0.144208",
"fee": "0.0005",
"liquidity_indicator": "MAKER",
"time": "1705317000000000000",
"is_liquidation": false,
"realized_pnl": "123.456",
"realized_pnl_percentage": "2.5",
"avg_price": "92000",
"position_side": "BUY",
"leverage": "10",
"margin_mode": "cross",
"blockchain_data": {
"tx_hash": "0xabc123def456...",
"block_number": 33759944,
"log_index": 211
}
},
"tx_hash": "0xabc123def456...",
"block_number": 33759944,
"log_index": 211,
"block_timestamp": "1705317000000000000",
"timestamp": "1705317000123456789"
}Update Message Fields
| Field | Type | Description |
|---|---|---|
channel | string | Always "fills" |
type | string | Always "update" |
market_id | string | Market ID |
data | object | Fill object (see below) |
tx_hash | string | Transaction hash |
block_number | number | Blockchain block number |
log_index | number | Log index within the block |
block_timestamp | string | Blockchain timestamp (nanoseconds) |
timestamp | string | Server timestamp (nanoseconds) |
Fill Object Fields
| Field | Type | Description |
|---|---|---|
id | string | Unique trade ID (maker_order_id-taker_order_id) |
market_id | string | Market ID |
order_id | string | Your order ID (maker or taker) |
side | string | Your trade side: "BUY" or "SELL" |
price | string | Trade price (decimal) |
size | string | Trade size (decimal) |
fee | string | Fee you paid (decimal) |
liquidity_indicator | string | "MAKER" or "TAKER" |
time | string | Trade time (nanoseconds) |
is_liquidation | boolean | Whether this is a liquidation |
realized_pnl | string | Realized PnL from this trade (decimal, optional) |
realized_pnl_percentage | string | Realized PnL percentage (decimal, optional) |
avg_price | string | Average entry price after trade (decimal, optional) |
position_side | string | Position side after trade: "BUY", "SELL", or "" |
leverage | string | Leverage (decimal, optional) |
margin_mode | string | "cross" or "isolated" (optional) |
blockchain_data | object | Blockchain metadata (optional) |
Blockchain Data Object
| Field | Type | Description |
|---|---|---|
tx_hash | string | Transaction hash |
block_number | number | Block number |
log_index | number | Log index within block |
Liquidity Indicator
| Value | Description |
|---|---|
MAKER | You provided liquidity (your order was resting on book) |
TAKER | You removed liquidity (your order crossed the spread) |
Position Side
| Value | Description |
|---|---|
BUY | Long position after this trade |
SELL | Short position after this trade |
"" | Flat (no position) after this trade |
PnL Calculation
realized_pnl: The realized profit/loss from this trade, calculated asAfter.RealizedPNL - Before.RealizedPNLrealized_pnl_percentage: Percentage relative to the position's entry cost
PnL fields are only present when there is realized PnL (position size decreased or flipped).
Examples
Subscribe to all fills
{
"method": "subscribe",
"params": {
"channel": "fills"
}
}Subscribe to specific markets
{
"method": "subscribe",
"params": {
"channel": "fills",
"market_ids": [1, 2]
}
}Unsubscribe
{
"method": "unsubscribe",
"params": {
"channel": "fills"
}
}Error Responses
Authentication Required
If you try to subscribe without authenticating first:
{
"method": "subscribe",
"status": "error",
"channel": "fills",
"message": "Failed to subscribe to fills: authentication required for fills channel"
}Testing with wscat
# Connect
wscat -c ws://localhost:8090/ws
# Authenticate first (replace with valid signature)
{"method":"auth","params":{"account":"0x...","signer":"0x...","message":"WebSocket Authentication","nonce":1703123456,"signature":"0x..."}}
# Subscribe to all fills
{"method":"subscribe","params":{"channel":"fills"}}
# Subscribe to market 1 only
{"method":"subscribe","params":{"channel":"fills","market_ids":[1]}}
# Unsubscribe
{"method":"unsubscribe","params":{"channel":"fills"}}Notes
No Snapshot
Unlike other channels (orders, positions), the fills channel does not send a snapshot on subscription. Historical fills are available via the REST /v1/trade-history endpoint.
Price Format
All price and size fields are in decimal format (human-readable), not wei.
- Example price:
"92995"= $92,995 - Example size:
"0.144208"= 0.144208 units
Real-time Delivery
Fills are broadcast immediately when the MatchOrder event is processed from the blockchain. There is no batching or throttling.
Private Channel
This channel requires authentication. You will only receive fills for your own account.
Difference from Trades Channel
| Aspect | Trades Channel | Fills Channel |
|---|---|---|
| Authentication | Not required | Required |
| Scope | All trades (public) | Your fills only (private) |
| PnL Data | No | Yes |
| Position Data | No | Yes (side, leverage, margin) |
| Order ID | Both maker/taker | Your order ID only |
| Fee | Both maker/taker | Your fee only |