Authenticated users automatically receive order and balance notifications over the WebSocket. No subscription action needed — just authenticate and events start flowing.
Connect and Authenticate
// Authenticate on connection by passing your JWT as a query param
const ws = new WebSocket(`wss://ws.agg.market/ws?appId=${appId}&token=${accessToken}`);
You’ll receive a confirmation:
{ "type": "connected", "appId": "your-app-id", "userId": "user-123" }
You can also authenticate mid-session (e.g. after the user signs in):
ws.send(JSON.stringify({ action: "authenticate", token: accessToken }));
// Response: { "type": "authenticated", "userId": "user-123" }
Once authenticated, all your order and balance events are delivered automatically. No separate subscription action is needed.
No initial state is sent on authentication — you only receive events for actions that happen after you connect. To get current balances or holdings, use the REST endpoints (GET /trading/balance, GET /trading/holdings).
Events
Order Submitted
Sent after a trade is successfully placed:
{
"type": "order_submitted",
"venue": "kalshi",
"orderId": "order-abc-123",
"side": "buy",
"price": 0.55,
"size": 10,
"marketId": "market-123",
"timestamp": 1710705123456
}
Balance Update
Sent after orders are placed, reflecting your updated balance:
{
"type": "balance_update",
"venue": "kalshi",
"tradingBalanceCents": 50000,
"walletBalanceCents": 100000,
"timestamp": 1710705123456
}
Handling Events
ws.onmessage = (event) => {
const msg = JSON.parse(event.data);
switch (msg.type) {
case "order_submitted":
addOrder({
id: msg.orderId,
venue: msg.venue,
side: msg.side,
price: msg.price,
size: msg.size,
});
break;
case "balance_update":
updateBalance(msg.venue, {
trading: msg.tradingBalanceCents / 100,
wallet: msg.walletBalanceCents ? msg.walletBalanceCents / 100 : null,
});
break;
}
};
Reconnection
If the connection drops, reconnect and re-authenticate. If your access token has expired, refresh it first:
function connect() {
const ws = new WebSocket(`wss://ws.agg.market/ws?appId=${appId}&token=${accessToken}`);
ws.onclose = async () => {
// Refresh token if needed
try {
const { accessToken: newToken } = await client.refreshToken({
refreshToken: storedRefreshToken,
});
accessToken = newToken;
} catch {
// Refresh failed — user needs to re-authenticate
return;
}
setTimeout(connect, 1000);
};
ws.onmessage = handleMessage;
}