Complete code examples for connecting to the Hydra WebSocket stream.
Code Examples
All examples require a valid API key. See API Keys to generate one.
JavaScript / Node.js
Basic connection with message handling
const API_KEY = 'hydra_k1_abc123...';
const ws = new WebSocket(`wss://api.hydra.fast/v1/stream?apiKey=${API_KEY}`);
ws.onopen = () => console.log('Connected to Hydra stream');
ws.onmessage = (event) => {
const { type, data } = JSON.parse(event.data);
switch (type) {
case 'connected':
console.log('Stream ready, scopes:', data.scopes);
break;
case 'aircraft':
console.log(`${data.count} aircraft positions`);
data.positions.forEach(ac => {
console.log(` ${ac.callsign || ac.icaoHex} [${ac.category}] ${ac.lat}, ${ac.lng}`);
});
break;
case 'signal':
data.signals.forEach(sig => {
console.log(`[${sig.severity}] ${sig.title}`);
});
break;
case 'alert':
data.alerts.forEach(alert => {
console.log(`ALERT: ${alert.title}`);
});
break;
case 'vessel':
console.log(`${data.count} vessel positions`);
break;
case 'market':
data.markets.forEach(m => {
if (Math.abs(m.priceChange) > 0.02) {
console.log(`Market move: ${m.question} (${(m.priceChange * 100).toFixed(1)}pp)`);
}
});
break;
}
};
ws.onclose = () => console.log('Disconnected');
ws.onerror = (err) => console.error('WebSocket error:', err);
Robust client with auto-reconnect
class HydraStream {
constructor(apiKey) {
this.apiKey = apiKey;
this.attempt = 0;
this.ws = null;
this.handlers = new Map();
}
on(type, handler) {
this.handlers.set(type, handler);
return this;
}
connect() {
this.ws = new WebSocket(`wss://api.hydra.fast/v1/stream?apiKey=${this.apiKey}`);
this.ws.onopen = () => {
console.log('Connected');
this.attempt = 0;
};
this.ws.onmessage = (event) => {
const { type, data } = JSON.parse(event.data);
const handler = this.handlers.get(type);
if (handler) handler(data);
};
this.ws.onclose = () => {
const delay = Math.min(1000 * Math.pow(2, this.attempt), 30000);
console.log(`Reconnecting in ${delay}ms...`);
setTimeout(() => {
this.attempt++;
this.connect();
}, delay);
};
}
disconnect() {
if (this.ws) this.ws.close();
}
}
// Usage
const stream = new HydraStream('hydra_k1_abc123...');
stream
.on('aircraft', (data) => {
console.log(`Tracking ${data.count} aircraft`);
})
.on('signal', (data) => {
data.signals.forEach(s => console.log(`[${s.severity}] ${s.title}`));
})
.on('alert', (data) => {
data.alerts.forEach(a => console.log(`ALERT: ${a.title}`));
})
.connect();
Python
Using websockets library
import asyncio
import json
import websockets
API_KEY = "hydra_k1_abc123..."
async def connect():
uri = f"wss://api.hydra.fast/v1/stream?apiKey={API_KEY}"
attempt = 0
while True:
try:
async with websockets.connect(uri) as ws:
print("Connected to Hydra stream")
attempt = 0
async for raw in ws:
message = json.loads(raw)
msg_type = message["type"]
data = message["data"]
if msg_type == "connected":
print(f"Stream ready, scopes: {data['scopes']}")
elif msg_type == "aircraft":
print(f"Aircraft: {data['count']} positions")
for ac in data["positions"]:
cs = ac.get("callsign") or ac["icaoHex"]
print(f" {cs} [{ac['category']}] {ac['lat']}, {ac['lng']}")
elif msg_type == "signal":
for sig in data["signals"]:
print(f"[{sig['severity']}] {sig['title']}")
elif msg_type == "alert":
for alert in data["alerts"]:
print(f"ALERT: {alert['title']}")
elif msg_type == "vessel":
print(f"Vessels: {data['count']} positions")
elif msg_type == "market":
for m in data["markets"]:
if abs(m.get("priceChange", 0)) > 0.02:
pct = m["priceChange"] * 100
print(f"Market: {m['question']} ({pct:+.1f}pp)")
except (websockets.ConnectionClosed, ConnectionError) as e:
delay = min(2 ** attempt, 30)
print(f"Disconnected: {e}. Reconnecting in {delay}s...")
await asyncio.sleep(delay)
attempt += 1
asyncio.run(connect())
Alert monitor (minimal)
import asyncio
import json
import websockets
API_KEY = "hydra_k1_abc123..."
async def monitor_alerts():
uri = f"wss://api.hydra.fast/v1/stream?apiKey={API_KEY}"
async with websockets.connect(uri) as ws:
async for raw in ws:
msg = json.loads(raw)
if msg["type"] == "alert":
for alert in msg["data"]["alerts"]:
print(f"[{alert['severity']}] {alert['title']}")
print(f" Region: {alert.get('region', 'N/A')}")
print(f" Time: {alert['createdAt']}")
asyncio.run(monitor_alerts())
Go
package main
import (
"encoding/json"
"fmt"
"log"
"net/http"
"time"
"github.com/gorilla/websocket"
)
const apiKey = "hydra_k1_abc123..."
type Message struct {
Type string `json:"type"`
Data json.RawMessage `json:"data"`
}
type AircraftData struct {
Count int `json:"count"`
Positions []struct {
IcaoHex string `json:"icaoHex"`
Callsign *string `json:"callsign"`
Lat float64 `json:"lat"`
Lng float64 `json:"lng"`
Category string `json:"category"`
} `json:"positions"`
}
func main() {
for attempt := 0; ; attempt++ {
err := stream()
if err != nil {
delay := min(time.Duration(1<<attempt)*time.Second, 30*time.Second)
log.Printf("Disconnected: %v. Reconnecting in %s...", err, delay)
time.Sleep(delay)
}
}
}
func stream() error {
url := "wss://api.hydra.fast/v1/stream?apiKey=" + apiKey
headers := http.Header{"x-api-key": {apiKey}}
c, _, err := websocket.DefaultDialer.Dial(url, headers)
if err != nil {
return err
}
defer c.Close()
log.Println("Connected")
for {
_, raw, err := c.ReadMessage()
if err != nil {
return err
}
var msg Message
json.Unmarshal(raw, &msg)
switch msg.Type {
case "aircraft":
var data AircraftData
json.Unmarshal(msg.Data, &data)
fmt.Printf("Aircraft: %d positions\n", data.Count)
case "signal":
fmt.Printf("Signal update received\n")
case "alert":
fmt.Printf("ALERT received\n")
}
}
}
CLI (websocat)
WebSocket connections aren't natively supported by cURL, but you can use websocat for testing:
# Install: cargo install websocat
websocat "wss://api.hydra.fast/v1/stream?apiKey=hydra_k1_abc123..." | jq .
Filter to specific event types:
websocat "wss://api.hydra.fast/v1/stream?apiKey=hydra_k1_abc123..." | \
jq 'select(.type == "alert" or .type == "signal")'