Skip to content

Dichit WebSocket API

The Dichit real-time API delivers live auction data, presence, notifications, and staff controls over a single authenticated WebSocket connection. Subscribers, companies, auctioneers, and administrators all use the same endpoint; the server derives each connection's identity, role, and permissions from the JWT presented during the handshake.

This documentation is the authoritative contract for the real-time API. It is written for frontend engineers, backend engineers, mobile developers, QA engineers, and third-party integrators.


Overview

The real-time API is a request/response protocol over WebSocket (RFC 6455) with a server-pushed event stream. Clients send JSON messages inside a common envelope, the server validates and authorizes each message, and responds with an acknowledgement (ack) or an error. State changes (new bids, auction state transitions, presence transitions) are pushed to clients asynchronously.

Key properties:

  • One endpoint for every role.
  • JWT authentication at connection time.
  • Permission-based, message-level authorization.
  • Room-based fan-out backed by Redis Pub/Sub, so any WebSocket server instance can deliver to any client.
  • Server-driven event log with sequence numbers, enabling snapshot + replay recovery after reconnection.

Endpoint

All roles connect to a single WebSocket endpoint:

Production:   wss://api.example.com/ws
Staging:      wss://api.staging.example.com/ws
Local dev:    ws://localhost:3500/ws

There are no role-specific endpoints. Requesting a path other than /ws is not supported. See connection.md.

Supported protocol

  • Transport: WebSocket (RFC 6455) over TLS (wss://). Plain ws:// is allowed only for local development.
  • Subprotocols:
  • websocket.v1 — current protocol version (use this).
  • auction-room.v1 — legacy, accepted for backward compatibility.
  • bearer.<access-token> — subprotocol used to carry the JWT when a custom Authorization header cannot be set (for example, in browsers).
  • Framing: JSON text frames. Binary frames are not supported.
  • The Sec-WebSocket-Protocol header may carry websocket.v1, bearer.<token>.

See connection.md and versioning.md.

Authentication

Authentication happens during the WebSocket handshake, before any message is processed. An access token (JWT, type: access) is required for every connection. Clients present the token either as a standard HTTP header or as a WebSocket subprotocol:

Authorization: Bearer <access-token>

or

Sec-WebSocket-Protocol: websocket.v1, bearer.<access-token>

Invalid, expired, or missing tokens close the connection with close code 1008 and reason Authentication failed.

Roles are derived from the token claim:

Role Description Key permissions
SUBSCRIBER Individual auction participant auction:subscribe, auction:bid:place, room:join, room:leave
COMPANY Company user / auctioneer staff auction:subscribe, auction:staff, broadcast:receive, room:join, room:leave
SUPERADMIN Platform administrator auction:subscribe, auction:staff, broadcast:receive, room:join, room:leave

See authentication.md.

Message format

Every client-to-server message uses the same envelope:

{
  "type": "auction.bid.place",
  "requestId": "req_01HQ5BXWYP1Y5RX0W5X0W5X0W5X",
  "timestamp": "2026-08-03T10:00:00.000Z",
  "data": {
    "cycleId": "cyc_01HQ5BXWYP1Y5RX0W5X0W5X0W5X",
    "amount": "25000",
    "idempotencyKey": "bid_req_01HQ5BY3K7Z2Z6Y0W5X0W5X0W5X"
  }
}
Field Type Required Description
type string Yes Dot-separated event name, e.g. auction.bid.place. 1–128 chars.
requestId string Yes (recommended) Client-generated identifier echoed back in acknowledgements and errors. 1–128 chars.
timestamp string Optional Client-side ISO-8601 timestamp. Server does not trust it for ordering.
data object Depends Event payload, validated against the per-event Zod schema.

Server responses come in two shapes, acknowledgements and errors:

{
  "type": "ack",
  "requestId": "req_01HQ5BXWYP1Y5RX0W5X0W5X0W5X",
  "eventType": "auction.bid.place",
  "data": {
    "auctionId": "auc_01HQ5BXWYP1Y5RX0W5X0W5X0W5X",
    "cycleId": "cyc_01HQ5BXWYP1Y5RX0W5X0W5X0W5X",
    "bidId": "bid_01HQ5BY3K7Z2Z6Y0W5X0W5X0W5X",
    "amount": 25000,
    "stateVersion": 7,
    "idempotencyKey": "bid_req_01HQ5BY3K7Z2Z6Y0W5X0W5X0W5X",
    "wasReplayed": false
  }
}
{
  "type": "error",
  "requestId": "req_01HQ5BXWYP1Y5RX0W5X0W5X0W5X",
  "code": "FORBIDDEN",
  "message": "You are not authorized to perform this WebSocket action."
}

Server-pushed events (bids, presence, auction state) use the same type / requestId / data shape; the type is the canonical event name such as bid.created.

See protocol.md for the full contract and errors.md for all error codes.

Rooms

State is distributed through named rooms. Clients join rooms they are allowed to see, and the server publishes updates to a room exactly once, regardless of how many WebSocket servers are running:

Room Purpose
auction:<cycleId> Live auction state, bids, and presence
company:<companyId> Company-scoped staff updates
user:<userId> Private updates for a single user
admins Platform-wide administrative broadcasts
notifications User notifications

Room membership is per-connection and cleared automatically when a connection closes. See rooms.md.

Documentation index

Getting started

Document Content
protocol.md Message envelope, request/response model, event naming, client/server events
connection.md Endpoint, TLS, reconnection, heartbeats, timeouts, message size
authentication.md JWT flow, token expiration, re-authentication, roles and permissions
rooms.md Room architecture, membership rules, lifetimes

Events

Document Content
events/system.md system.ping, system.pong
events/auth.md auth.login, auth.logout
events/auction.md auction.subscribe, auction.unsubscribe, auction.bid.place, auction.bid.cancel, auction.started, auction.updated, auction.ended, auction.bid.created, staff commands, server events
events/company.md Company-scoped events and the company:{companyId} room
events/presence.md presence.joined, presence.left, presence.update, presence.changed
events/notification.md notification.created, notification.read
events/chat.md chat.send, chat.typing

Reference

Document Content
errors.md Error codes, HTTP equivalents, retryability, examples
rate-limits.md Per-event limits and server behaviour when exceeded
lifecycle.md Full connection lifecycle: connect → auth → join → updates → heartbeat → disconnect → reconnect
versioning.md Protocol versioning, compatibility, deprecation policy
diagrams.md Mermaid diagrams for connection, auth, bidding, broadcast, Redis Pub/Sub, scaling, rooms, routing, and authorization

Implementation status

The following events are part of the documented contract. The current server build marks events as Implemented (registered socket routes) or Planned (contract defined, route not yet registered). Integrators should gate on the Implemented set; Planned events are documented so contracts evolve in a backward-compatible way.

Domain Implemented Planned
System system.ping system.pong is the response shape
Rooms room.join, room.leave
Auction (client) auction.subscribe, auction.unsubscribe, auction.bid.place, auction.status.update, auction.pause, auction.resume, auction.end, bid.mark, winner.declare, winner.record_lot auction.bid.cancel
Auction (server) auction.connected, auction.snapshot, presence.snapshot, auction.started, auction.paused, auction.resumed, auction.extended, auction.call_started, auction.closed, auction.winner_selected, auction.state_refreshed, auction.status_changed, bid.created, bid.updated, bid.rejected, bid.deleted, prebid.deleted, bidder.disqualified, presence.joined, presence.left, presence.changed auction.updated, auction.ended, auction.bid.created (documented aliases of canonical events)
Auth (in-band) auth.login, auth.logout (authentication is performed at the handshake)
Presence (client) presence.update (presence is server-managed)
Notification notification.created, notification.read
Chat chat.send, chat.typing

Each event page in events/ states its implementation status and, where names differ from the canonical server event, the mapping in Notes.