WebSocket API

Overview

WebSocket API overview, connection lifecycle, and channel model

Use the WebSocket API for market streams and private account updates.

Endpoint

EnvironmentURL
Productionwss://pulse.obsdn.trade/ws
Testnetwss://pulse.staging.obsdn.trade/ws

Quick Start

# Using wscat (production)
wscat -c wss://pulse.obsdn.trade/ws

# Testnet
wscat -c wss://pulse.staging.obsdn.trade/ws
const ws = new WebSocket("wss://pulse.obsdn.trade/ws")

ws.onopen = () => {
  ws.send(
    JSON.stringify({
      op: "sub",
      channel: "ticker",
      params: { market: "BTC-PERP" },
    })
  )
}

ws.onmessage = (event) => {
  console.log(JSON.parse(event.data))
}

Message Model

Subscribe

{
  "op": "sub",
  "channel": "CHANNEL_NAME",
  "params": { "market": "MARKET_ID" }
}

Unsubscribe

{
  "op": "unsub",
  "channel": "CHANNEL_NAME",
  "params": { "market": "MARKET_ID" }
}

The params field is channel-specific. Market channels use { "market": "BTC-PERP" }, the oracle channel uses { "asset": "BTC" }, and private user channels require no params, though order and position accept an optional { "market": "BTC-PERP" } filter.

Auth (for private channels)

Send before subscribing to any private channel.

{
  "op": "auth",
  "params": {
    "key": "your_api_key",
    "timestamp": "1734567890",
    "signature": "your_signature"
  }
}

The signature is computed as base64(HMAC-SHA256(api_secret, "${api_key},${timestamp}")), using standard base64 encoding.

timestamp is a Unix time in seconds (string) and must be within ±60 seconds of server time, otherwise the auth message is rejected.

import { createHmac } from "node:crypto"

const timestamp = Math.floor(Date.now() / 1000).toString()
const signature = createHmac("sha256", apiSecret).update(`${apiKey},${timestamp}`).digest("base64")

Connection

On connect, the server sends a welcome message with a unique connection identifier:

{ "type": "welcome", "connection_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890" }

Auth Response

After a successful auth message, the server responds with:

{ "type": "authenticated", "address": "0xYourWalletAddress" }

The address field confirms which wallet the connection is authenticated as.

Heartbeat

The server sends periodic pings and will disconnect if it receives no pong within 60 seconds. Clients may send their own pings for keepalive (the server will respond with a pong); they are not required to.

{ "op": "ping" }
{ "type": "pong" }

Subscribed Confirmation

After a successful subscription, the server sends:

{
  "type": "subscribed",
  "channel": "CHANNEL_NAME",
  "params": { "market": "BTC-PERP" }
}

The params field echoes back the subscription parameters (omitted if no params were provided).

Channel Summary

ChannelAuthparamsSnapshotUpdates
bookNo{ market }YesYes
tradeNo{ market } (optional)YesYes
tickerNo{ market }YesYes
oracleNo{ asset }YesYes
candleNo{ market }YesYes
orderYes{ market } (optional)YesYes
positionYes{ market } (optional)YesYes
portfolioYesNoneYesYes
notificationYesNoneNoYes

Connection Guidance

  1. Implement automatic reconnect with exponential backoff.
  2. Resubscribe to all channels after reconnect.
  3. Process messages in-order per channel/market stream.
  4. Validate order book checksums and resubscribe on mismatch.
  5. Respond to server pings with a pong; reconnect if disconnected.

Next

On this page