Auction Room Frontend Integration Guide¶
Use one WebSocket endpoint for every auction realtime role:
Subscribers, companies, and admins all connect to the same URL. The server authorizes each message from the authenticated JWT context.
Authentication¶
Native and mobile clients can send the token as an HTTP header:
Browser clients usually cannot set custom WebSocket headers, so send the token through Sec-WebSocket-Protocol:
auction-room.v1 is also accepted for protocol compatibility.
Invalid or missing tokens close the socket with policy violation code 1008.
Message Contract¶
Every client message must be JSON:
Rules:
typeis required and must match a registered eventrequestIdis optional but recommended for correlating acknowledgementsdatais validated per event- Use
data, not the removedpayloadfield
Successful command acknowledgements look like:
Errors look like:
{
"type": "error",
"requestId": "request-id",
"code": "FORBIDDEN",
"message": "Safe client-facing message."
}
Known error codes:
Recommended Client Flow¶
- Open
/wswith a valid access token. - Send
auction.subscribefor the active cycle. - Wait for the initial server events.
- Render the latest
auction.snapshotandpresence.snapshot. - Send commands such as
auction.bid.place. - Apply pushed auction events such as
bid.created. - Send
auction.unsubscribewhen leaving the screen. - Reconnect and resubscribe after network loss.
Subscribe As Subscriber¶
Subscribers include enrolledSubscriberId:
{
"type": "auction.subscribe",
"requestId": "subscribe-001",
"data": {
"cycleId": "cycle-id",
"enrolledSubscriberId": "enrolled-subscriber-id"
}
}
The server sends these initial events:
It also returns an acknowledgement:
{
"type": "ack",
"requestId": "subscribe-001",
"eventType": "auction.subscribe",
"data": {
"auctionId": "auction-id",
"cycleId": "cycle-id",
"room": "auction:cycle-id"
}
}
Subscribe As Company Or Admin¶
Company and superadmin users omit enrolledSubscriberId:
Staff snapshots can include staff-only auction state such as the full subscriber room view when authorized by the application use case.
Resume With Replay¶
Clients that persisted the last processed auction sequence can request replay data:
{
"type": "auction.subscribe",
"requestId": "subscribe-002",
"data": {
"cycleId": "cycle-id",
"enrolledSubscriberId": "enrolled-subscriber-id",
"lastSequence": 42
}
}
When replay is available, the server merges it into the auction.snapshot payload.
Place A Bid¶
Only subscriber connections can place live bids.
{
"type": "auction.bid.place",
"requestId": "bid-001",
"data": {
"cycleId": "cycle-id",
"enrolledSubscriberId": "enrolled-subscriber-id",
"amount": "25000",
"idempotencyKey": "bid-001"
}
}
Use decimal strings for money values to avoid JavaScript precision surprises. The idempotencyKey should be stable for retries of the same bid action.
Successful acknowledgement:
{
"type": "ack",
"requestId": "bid-001",
"eventType": "auction.bid.place",
"data": {
"bidId": "bid-id",
"stateVersion": 7
}
}
The client may also receive auction realtime events before or after the acknowledgement, for example:
{
"type": "bid.created",
"requestId": "bid-001",
"data": {
"auctionId": "auction-id",
"cycleId": "cycle-id",
"stateVersion": 7,
"occurredAt": "2026-08-03T00:00:00.000Z",
"payload": {
"bidId": "bid-id",
"leadingBidAmount": 25000
}
}
}
Unsubscribe¶
{
"type": "auction.unsubscribe",
"requestId": "unsubscribe-001",
"data": {
"cycleId": "cycle-id"
}
}
Successful acknowledgement:
{
"type": "ack",
"requestId": "unsubscribe-001",
"eventType": "auction.unsubscribe",
"data": {
"cycleId": "cycle-id",
"unsubscribed": true
}
}
Application Ping¶
The server also has protocol-level heartbeat pings. This event is for client application-level health checks.
Acknowledgement data:
{
"type": "ack",
"requestId": "ping-001",
"eventType": "system.ping",
"data": {
"type": "system.pong",
"occurredAt": "2026-08-03T00:00:00.000Z"
}
}
Generic Rooms¶
The frontend can join controlled generic rooms when needed:
Allowed room names:
admins is only available to SUPERADMIN. company:<id> must match the authenticated company context.
Leave a room:
Reconnection Guidance¶
On socket close:
- Open a new
/wsconnection with a fresh access token if needed - Send
auction.subscribeagain - Include
lastSequencewhen the client has processed a sequence number - Rebuild UI from the latest snapshot, then apply pushed events
If the access token expires, refresh it through the normal HTTP auth flow before opening a new socket.
Rate Limits¶
Default limit:
auction.bid.place limit:
Limits are applied per authenticated user, per IP, and per event type. A rate-limited message receives:
{
"type": "error",
"requestId": "bid-001",
"code": "RATE_LIMITED",
"message": "Too many WebSocket messages."
}
Removed WebSocket Routes¶
Do not use legacy role-specific auction WebSocket URLs. They have been removed. All realtime auction traffic now flows through the single /ws endpoint.