Authentication
The WebSocket isn’t authenticated byapi-key (browsers can’t send
custom headers on WebSocket upgrades). Instead, mint a short-lived JWT
ticket through the API, then pass it as a ?token= query string.
1
Mint a ticket
Call
POST /auth/ws-token with On-Behalf-Of set to the sub-user
you want to subscribe as. Each ticket is bound to that one sub-user.2
Open the socket
The token can ride in either of two slots. The subprotocol form is
preferred — the token isn’t logged by proxies / browser history /
access logs the way query strings are:The server verifies the ticket on upgrade. Bad token → close code
4001 Invalid token.3
Listen for the connected frame
Immediately after upgrade, the server pushes:
Protocol
- Read-only. Sending any frame to the server closes the socket with
4002 Read-only. The protocol carries server pushes only. - Heartbeats. The server sends WS pings; respond with pongs to keep the connection alive (most clients do this automatically).
- Frame shape. Every push is
{ event, data, ts }—eventis a string discriminator,tsis Unix epoch milliseconds.
Events
Discriminating deposits
Gateway-hosted deposits (Gate Pay, on-ramp) and self-hosted EVM crypto share event names but carry different keys:Trade events
Fired on every status transition. The full trade payload is included so you can update your UI without a follow-up GET.Close codes
Reconnection
The server doesn’t rotate tokens on disconnect; the same ticket is valid until it expires (~1h). On disconnect:One sub-user per socket
A token is bound to theOn-Behalf-Of sub-user it was minted with — the
socket only delivers events for that user. To watch multiple sub-users,
mint a token per sub-user and open one socket each. There’s no
multi-subscription pattern on a single connection.
For server-side aggregation across many sub-users, prefer
Webhooks.