Realtime
WebSocket
Connect to the realtime WebSocket endpoint and handle live events.
Endpoint
Use:
GET /api/v1/ws?token=<access_token>
Although the handler comments mention Authorization support, the route is currently
wrapped by WebSocketAuthMiddleware(), which requires the token in the query string.
For a browser or mobile client, that means the practical connection URL is:
wss://<host>/api/v1/ws?token=<access_token>
Authentication Behavior
- The
tokenquery parameter must contain a valid current access token. - If the token is missing, expired, or revoked, the connection is rejected before upgrade.
- The server resolves the mobile user from Redis-backed access-token state.
Connection Notes
- The endpoint upgrades to WebSocket only when WebSocket is enabled in backend config.
- Origin checks use the backend
AllowedOriginsconfiguration. - Each new connection is intended to replace older sockets for the same user. Do not rely on multiple concurrent sockets for one account.
- Every new client is auto-subscribed to the
settingschannel on connect.
Client Messages
After connecting, the client can send plain JSON messages.
Subscribe to a channel
{
"event": "subscribe",
"channel": "notification.events"
}
Unsubscribe from a channel
{
"event": "unsubscribe",
"channel": "notification.events"
}
Ping
{
"event": "ping"
}
The socket layer also sends protocol-level ping frames on a timer.
Server Event Envelope
Realtime events are sent in this shape:
{
"event": "NOTIFICATION_UPDATE",
"channel": "notification.events",
"data": {}
}
Fields:
| Field | Meaning |
|---|---|
event | Event name / event type emitted by the backend |
channel | Logical channel for filtering and subscriptions |
data | Event-specific payload |
Common Channels
| Channel | Purpose |
|---|---|
settings | Auto-subscribed channel for global settings updates |
notification.events | User notification unread-count updates |
payment_order.events | Payment and recharge status updates |
card.events | Card status updates |
card.create.events | Card create/request flow updates |
card.withdraw.events | Card withdrawal updates |
kyc.events | KYC state changes |
mobile.force.logout | Forced logout events |
Example Events
Notification unread count update
{
"event": "NOTIFICATION_UPDATE",
"channel": "notification.events",
"data": {
"mobile_user_id": 120045,
"unread_count": 3,
"event_type": "NOTIFICATION_UPDATE",
"timestamp": 1740748800
}
}
Global settings update
{
"event": "withdrawal_settings_updated",
"channel": "settings",
"data": {
"type": "withdrawal_settings_updated",
"withdrawal_fee_rate": "1.50"
}
}
Force logout
{
"event": "MOBILE_USER_FORCE_LOGOUT_EVENT",
"channel": "mobile.force.logout",
"data": {
"mobile_user_id": 120045,
"is_force_logout": true
}
}
Diagnostic Endpoints
These HTTP endpoints exist alongside the socket endpoint:
GET /api/v1/ws/connected-usersRequires bearer auth and returns connected user IDs.GET /api/v1/ws/connectionsReturns detailed connection info. In the current router setup, this is registered without explicit auth middleware, so treat it as an internal diagnostic endpoint.GET /api/v1/ws/test?user_id=<id>No-auth stress-test endpoint. Do not use it in production clients.
Failure Shape Before Upgrade
If the server rejects the connection before WebSocket upgrade, the API returns the same JSON error style used by HTTP endpoints, for example:
{
"status_code": 401,
"message": "Invalid or expired token",
"trace_id": "2a6d1a45d8c9402d",
"data": null
}