Overview
The /ws/v1/user endpoint streams real-time updates for your own orders. Unlike the public market data endpoint, this requires authentication on every message.
wss://socket.bayse.markets/ws/v1/user
| Subscription | Channel | Server event types | Description |
|---|
| Orders | orders | order_updated | Fill updates for your orders on specific markets. |
Authentication
Every message you send to /ws/v1/user must include an auth field with either your API key or access token. The connection upgrade itself does not require credentials; authentication is verified per message.
{
"auth": {
"apiKey": "pk_live_..."
}
}
Or with an access token:
{
"auth": {
"accessToken": "eyJhbGciOiJIUzI1NiIs..."
}
}
| Field | Type | Description |
|---|
auth.accessToken | string | Your JWT access token. Required if apiKey is not provided. |
auth.apiKey | string | Your API public key. Required if accessToken is not provided. |
auth.deviceId | string | Optional device identifier. Sent alongside accessToken. |
Prefer apiKey for relay trading clients. If both accessToken and apiKey are provided, the access token takes precedence. The server caches your last verified credential per connection, so repeated messages with the same value skip the auth service call.
If auth is missing or invalid, the server returns an error:
{
"type": "error",
"data": {
"message": "auth required: include {\"auth\":{\"accessToken\":\"...\"}} or {\"auth\":{\"apiKey\":\"...\"}} in every message"
},
"timestamp": 1700000000000
}
Orders
Subscribe to your own order events for specific markets. You receive order_updated events when your order is partially or fully filled.
Subscribe
{
"type": "subscribe",
"channel": "orders",
"marketIds": ["MARKET_ID_1", "MARKET_ID_2"],
"auth": {
"apiKey": "pk_live_..."
}
}
marketIds supports up to 10 markets per subscription message. To track more markets, send multiple subscribe messages. For relay API clients, use the same public API key you use for authenticated HTTP requests.
Room names: orders:<userId>:<marketId> (one room per market)
Events received
order_updated — Your order was partially or fully filled.
{
"type": "order_updated",
"data": {
"orderId": "7f5e2a1c-3b4d-4e6f-8a9b-1c2d3e4f5a6b",
"eventId": "a1b2c3d4-5e6f-7a8b-9c0d-1e2f3a4b5c6d",
"marketId": "b2c3d4e5-6f7a-8b9c-0d1e-2f3a4b5c6d7e",
"order": {
"id": "7f5e2a1c-3b4d-4e6f-8a9b-1c2d3e4f5a6b",
"userId": "68eea9d8-a0fe-4534-ae88-b71e2f4f5c8f",
"marketId": "b2c3d4e5-6f7a-8b9c-0d1e-2f3a4b5c6d7e",
"outcomeId": "c3d4e5f6-7a8b-9c0d-1e2f-3a4b5c6d7e8f",
"outcomeLabel": "Yes",
"side": "BUY",
"price": 0.65,
"quantity": 150.0,
"filledQuantity": 100.0,
"remainingQuantity": 50.0,
"avgFillPrice": 0.64,
"status": "PARTIAL_FILLED",
"timeInForce": "GTC",
"createdAt": 1700000000,
"updatedAt": 1700000050
},
"timestamp": 1700000050
},
"timestamp": 1700000050000
}
Order fields
| Field | Type | Present on | Description |
|---|
id | string | All | Order UUID. |
userId | string | All | Your user UUID. |
marketId | string | All | Market UUID. |
outcomeId | string | All | Outcome UUID. |
outcomeLabel | string | All | Outcome label (e.g. “Yes”, “No”). |
side | string | All | BUY or SELL. |
price | number | All | Limit price (0.01 to 0.99). |
quantity | number | All | Original order quantity. |
filledQuantity | number | All | Quantity filled so far. |
remainingQuantity | number | All | Quantity remaining. |
avgFillPrice | number | order_updated | Volume-weighted average fill price. |
status | string | All | OPEN, PARTIAL_FILLED, FILLED, or CANCELLED. |
timeInForce | string | When present | GTC, IOC, or FOK. Omitted if empty. |
createdAt | number | All | Unix timestamp (seconds). |
updatedAt | number | All | Unix timestamp (seconds). |
Timestamps inside data.order and data.timestamp are Unix seconds. The outer timestamp field is Unix milliseconds.
Unsubscribe
{ "type": "unsubscribe", "room": "orders:USER_ID:MARKET_ID" }
Event series and market rotation
For events that belong to a series (e.g. hourly BTC markets), each interval produces a new event with new market IDs. When the current event closes and the next one opens, you must unsubscribe from the old market IDs and subscribe to the new market IDs.
The server does not automatically migrate your subscription to the next market in the series.
A subscription to orders:<userId>:<oldMarketId> does not follow the series forward. If you keep listening to the previous market after the next event opens, you will stop receiving new order updates for the series until you rotate to the new market IDs.
A recommended approach:
- Use the Get series events endpoint to find the currently open event.
- Subscribe to its market IDs.
- When you receive the last fill or detect that the event has closed, unsubscribe from the old market IDs.
- Fetch the newly opened event in the series and subscribe to its market IDs.
Forgetting to rotate subscriptions is a common issue. If you stop receiving order events after a series interval elapses, check that you are subscribed to the new market’s IDs, not the previous one’s.
Full example
const ws = new WebSocket("wss://socket.bayse.markets/ws/v1/user");
const auth = { apiKey: "pk_live_..." };
ws.addEventListener("open", () => {
ws.send(JSON.stringify({
type: "subscribe",
channel: "orders",
marketIds: ["MARKET_ID"],
auth,
}));
});
ws.addEventListener("message", (event) => {
for (const line of event.data.split("\n")) {
if (!line.trim()) continue;
const msg = JSON.parse(line);
switch (msg.type) {
case "order_updated":
console.log("Fill:", msg.data.order.filledQuantity, "at", msg.data.order.avgFillPrice);
break;
}
}
});