Skip to main content

WebSocket API

Real-time data streaming via WebSocket. Connect to /v1/stream to receive live updates with topic-based subscriptions, CloudEvents 1.0 message envelopes, and sequence-based resume.

Connection

wss://api.crypton.dev/v1/stream?token=YOUR_TOKEN

Query Parameters

ParameterTypeDefaultDescription
tokenstringRequired. Authentication token for the connection
symbolsstring(Deprecated) Comma-separated symbols. Use topic subscriptions instead
last_seqintegerSequence number to resume from. Server replays missed messages

Authentication

All WebSocket connections require a token passed as a query parameter on upgrade:
wss://api.crypton.dev/v1/stream?token=your-secret-token
Connections without a valid token are rejected with HTTP 401.

Topic Subscriptions

After connecting, subscribe to data topics by sending a JSON message:
{
  "action": "subscribe",
  "topics": ["funding:BTC", "funding:ETH", "oi:SOL"]
}

Topic Format

Topics use the format {type}:{symbol}:
Topic TypeDescriptionExample
fundingFunding rate updatesfunding:BTC
oiOpen interest changesoi:ETH
pricePrice updatesprice:SOL
liquidationLiquidation eventsliquidation:BTC

Wildcard Subscriptions

Use * to match all symbols for a type, or all types for a symbol:
{
  "action": "subscribe",
  "topics": ["funding:*", "*:BTC"]
}
PatternMatches
funding:*Funding updates for all symbols
*:BTCAll update types for BTC
funding:BTCOnly funding updates for BTC

Unsubscribe

{
  "action": "unsubscribe",
  "topics": ["funding:ETH"]
}

CloudEvents Envelope

All messages from the server use the CloudEvents 1.0 specification envelope:
{
  "specversion": "1.0",
  "id": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
  "source": "/v1/stream",
  "type": "funding.update",
  "time": "2026-03-13T12:00:05Z",
  "sequence": 10542,
  "data": {
    "symbol": "BTC",
    "exchange": "binance",
    "rate": 0.0100,
    "next_funding": "2026-03-13T16:00:00Z",
    "updated_at": 1709640005000
  }
}

Envelope Fields

FieldTypeDescription
specversionstringAlways "1.0"
idstringUnique event ID (UUID v4)
sourcestringEvent source path (/v1/stream)
typestringEvent type (e.g., funding.update, oi.update, price.update, liquidation.event)
timestringISO 8601 timestamp of the event
sequenceintegerMonotonically increasing sequence number for resume support
dataobjectEvent payload (varies by type — see below)

Message Types

Funding Update (funding.update)

{
  "specversion": "1.0",
  "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "source": "/v1/stream",
  "type": "funding.update",
  "time": "2026-03-13T12:00:05Z",
  "sequence": 10542,
  "data": {
    "symbol": "BTC",
    "exchange": "binance",
    "rate": 0.0100,
    "next_funding": "2026-03-13T16:00:00Z",
    "updated_at": 1709640005000
  }
}

Open Interest Update (oi.update)

{
  "specversion": "1.0",
  "id": "b2c3d4e5-f6a7-8901-bcde-f12345678901",
  "source": "/v1/stream",
  "type": "oi.update",
  "time": "2026-03-13T12:00:05Z",
  "sequence": 10543,
  "data": {
    "symbol": "ETH",
    "exchange": "binance",
    "oi_usd": 3200000000.0,
    "oi_contracts": 910540.0,
    "updated_at": 1709640005000
  }
}

Price Update (price.update)

{
  "specversion": "1.0",
  "id": "c3d4e5f6-a7b8-9012-cdef-123456789012",
  "source": "/v1/stream",
  "type": "price.update",
  "time": "2026-03-13T12:00:05Z",
  "sequence": 10544,
  "data": {
    "symbol": "BTC",
    "exchange": "binance",
    "price": 71000.50,
    "volume_24h": 1500000000,
    "updated_at": 1709640005000
  }
}

Liquidation Event (liquidation.event)

{
  "specversion": "1.0",
  "id": "d4e5f6a7-b8c9-0123-defa-234567890123",
  "source": "/v1/stream",
  "type": "liquidation.event",
  "time": "2026-03-13T12:00:05Z",
  "sequence": 10545,
  "data": {
    "symbol": "BTC",
    "exchange": "binance",
    "side": "long",
    "quantity": 1.5,
    "price": 70850.00,
    "usd_value": 106275.00,
    "updated_at": 1709640005000
  }
}

Sequence Resume

If your client disconnects, reconnect with the last_seq parameter to replay missed messages:
wss://api.crypton.dev/v1/stream?token=YOUR_TOKEN&last_seq=10540
The server replays all messages with sequence > 10540 in order before streaming new events.
The replay buffer is bounded. If too many messages have occurred since your last_seq, the server sends from the earliest available sequence and includes a replay.gap event to indicate missed data.

Backpressure

Each client connection has a 512-message bounded channel. If a client cannot consume messages fast enough:
  • New messages are dropped for that client (other clients are unaffected)
  • The server logs a warning but does not disconnect the client
  • Clients should monitor sequence gaps to detect dropped messages
If you see sequence gaps in production, your consumer is too slow. Consider subscribing to fewer topics or processing messages asynchronously.

Backward Compatibility

The old connection and subscription formats still work:
# Old query-param style (still supported)
wss://api.crypton.dev/v1/stream?symbols=BTC,ETH

# Old subscribe message (still supported)
{"subscribe": ["BTC", "ETH"]}
Legacy connections receive the same CloudEvents-wrapped messages. We recommend migrating to topic-based subscriptions for finer-grained control.

JavaScript Example

const ws = new WebSocket("wss://api.crypton.dev/v1/stream?token=YOUR_TOKEN");

ws.onopen = () => {
  // Subscribe to specific topics
  ws.send(JSON.stringify({
    action: "subscribe",
    topics: ["funding:BTC", "funding:ETH", "oi:BTC", "price:*"]
  }));
};

let lastSeq = 0;

ws.onmessage = (event) => {
  const msg = JSON.parse(event.data);

  // Track sequence for resume
  lastSeq = msg.sequence;

  switch (msg.type) {
    case "funding.update":
      console.log(`${msg.data.exchange} ${msg.data.symbol} funding: ${msg.data.rate}`);
      break;
    case "oi.update":
      console.log(`${msg.data.exchange} ${msg.data.symbol} OI: $${msg.data.oi_usd}`);
      break;
    case "price.update":
      console.log(`${msg.data.exchange} ${msg.data.symbol}: $${msg.data.price}`);
      break;
    case "liquidation.event":
      console.log(`${msg.data.exchange} ${msg.data.symbol} ${msg.data.side} liq: $${msg.data.usd_value}`);
      break;
  }
};

ws.onclose = () => {
  console.log("Disconnected, reconnecting with resume...");
  const resumeWs = new WebSocket(
    `wss://api.crypton.dev/v1/stream?token=YOUR_TOKEN&last_seq=${lastSeq}`
  );
  // ... re-subscribe to topics
};

Python Example

import json
import websockets
import asyncio

async def stream():
    uri = "wss://api.crypton.dev/v1/stream?token=YOUR_TOKEN"
    async with websockets.connect(uri) as ws:
        await ws.send(json.dumps({
            "action": "subscribe",
            "topics": ["funding:*", "*:BTC"]
        }))

        async for message in ws:
            event = json.loads(message)
            print(f"[{event['type']}] seq={event['sequence']} {event['data']}")

asyncio.run(stream())

Connection Notes

  • Server pushes updates every ~5 seconds per symbol per exchange
  • All messages wrapped in CloudEvents 1.0 envelope
  • 512-message bounded channel per client (drops on overflow)
  • Token authentication required on connection upgrade
  • Reconnect with last_seq to resume from where you left off
  • Implement exponential backoff on disconnect

Live Testing

# Using websocat (install: cargo install websocat)
echo '{"action":"subscribe","topics":["funding:BTC","oi:ETH"]}' | \
  websocat "wss://api.crypton.dev/v1/stream?token=YOUR_TOKEN"

# Using wscat (install: npm i -g wscat)
wscat -c "wss://api.crypton.dev/v1/stream?token=YOUR_TOKEN"
# Then type: {"action":"subscribe","topics":["funding:*"]}

# Resume from sequence 10000
websocat "wss://api.crypton.dev/v1/stream?token=YOUR_TOKEN&last_seq=10000"