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 token query 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 AllowedOrigins configuration.
  • 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 settings channel 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:

FieldMeaning
eventEvent name / event type emitted by the backend
channelLogical channel for filtering and subscriptions
dataEvent-specific payload

Common Channels

ChannelPurpose
settingsAuto-subscribed channel for global settings updates
notification.eventsUser notification unread-count updates
payment_order.eventsPayment and recharge status updates
card.eventsCard status updates
card.create.eventsCard create/request flow updates
card.withdraw.eventsCard withdrawal updates
kyc.eventsKYC state changes
mobile.force.logoutForced 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-users Requires bearer auth and returns connected user IDs.
  • GET /api/v1/ws/connections Returns 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
}
Copyright © 2026