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
| Parameter | Type | Default | Description |
|---|
token | string | — | Required. Authentication token for the connection |
symbols | string | — | (Deprecated) Comma-separated symbols. Use topic subscriptions instead |
last_seq | integer | — | Sequence 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"]
}
Topics use the format {type}:{symbol}:
| Topic Type | Description | Example |
|---|
funding | Funding rate updates | funding:BTC |
oi | Open interest changes | oi:ETH |
price | Price updates | price:SOL |
liquidation | Liquidation events | liquidation:BTC |
Wildcard Subscriptions
Use * to match all symbols for a type, or all types for a symbol:
{
"action": "subscribe",
"topics": ["funding:*", "*:BTC"]
}
| Pattern | Matches |
|---|
funding:* | Funding updates for all symbols |
*:BTC | All update types for BTC |
funding:BTC | Only 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
| Field | Type | Description |
|---|
specversion | string | Always "1.0" |
id | string | Unique event ID (UUID v4) |
source | string | Event source path (/v1/stream) |
type | string | Event type (e.g., funding.update, oi.update, price.update, liquidation.event) |
time | string | ISO 8601 timestamp of the event |
sequence | integer | Monotonically increasing sequence number for resume support |
data | object | Event 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"