WebSocket API
Receive real-time updates for bans, server status, and other events via WebSocket.
Connection
Endpoint
wss://bloqd.example.com/ws
Authentication
Include the API key or JWT token in the connection:
Via Query Parameter:
wss://bloqd.example.com/ws?token=f2b_your_api_key
Via Header (when client supports):
const ws = new WebSocket('wss://bloqd.example.com/ws', [], {
headers: {
'Authorization': 'Bearer f2b_your_api_key'
}
});
Message Format
All messages are JSON-encoded:
{
"type": "event_type",
"data": { ... },
"timestamp": "2024-01-15T10:30:00Z"
}
Event Types
ban
Triggered when an IP is banned.
{
"type": "ban",
"data": {
"id": 12345,
"ip": "192.168.1.100",
"jail": "sshd",
"server": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"hostname": "web-server-01"
},
"country": "CN",
"log_lines": "Failed password for root..."
},
"timestamp": "2024-01-15T10:30:00Z"
}
unban
Triggered when an IP is unbanned.
{
"type": "unban",
"data": {
"ip": "192.168.1.100",
"jail": "sshd",
"server": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"hostname": "web-server-01"
},
"reason": "ban_expired"
},
"timestamp": "2024-01-15T11:30:00Z"
}
server_status
Triggered when server status changes.
{
"type": "server_status",
"data": {
"server": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"hostname": "web-server-01"
},
"status": "offline",
"previous_status": "online",
"last_heartbeat": "2024-01-15T10:25:00Z"
},
"timestamp": "2024-01-15T10:30:00Z"
}
server_metrics
Periodic server metrics update.
{
"type": "server_metrics",
"data": {
"server": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"hostname": "web-server-01"
},
"metrics": {
"cpu_percent": 25.5,
"memory_percent": 60.2,
"disk_percent": 45.0
}
},
"timestamp": "2024-01-15T10:30:00Z"
}
command_result
Triggered when a remote command completes.
{
"type": "command_result",
"data": {
"command_id": "cmd-abc123",
"type": "ban-ip",
"status": "completed",
"result": {
"success": true,
"output": "IP banned successfully"
},
"server": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"hostname": "web-server-01"
}
},
"timestamp": "2024-01-15T10:30:05Z"
}
whitelist_update
Triggered when whitelist is modified.
{
"type": "whitelist_update",
"data": {
"action": "add",
"entry": {
"id": 16,
"ip": "203.0.113.100",
"description": "New entry"
},
"user": "admin"
},
"timestamp": "2024-01-15T10:30:00Z"
}
sync_complete
Triggered when whitelist sync completes.
{
"type": "sync_complete",
"data": {
"server": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"hostname": "web-server-01"
},
"status": "success",
"entries_synced": 15
},
"timestamp": "2024-01-15T10:30:00Z"
}
Subscribing to Events
Subscribe
Send a subscribe message to filter events:
{
"action": "subscribe",
"events": ["ban", "unban", "server_status"]
}
Response:
{
"type": "subscribed",
"events": ["ban", "unban", "server_status"]
}
Subscribe to Specific Server
{
"action": "subscribe",
"events": ["ban", "server_metrics"],
"server_id": "550e8400-e29b-41d4-a716-446655440000"
}
Unsubscribe
{
"action": "unsubscribe",
"events": ["server_metrics"]
}
Heartbeat
The server sends periodic pings:
{
"type": "ping",
"timestamp": "2024-01-15T10:30:00Z"
}
Respond with:
{
"action": "pong"
}
Connections that don't respond to pings within 30 seconds are closed.
Connection States
| State | Description |
|---|---|
connecting | WebSocket handshake in progress |
open | Connection established |
closing | Connection is being closed |
closed | Connection closed |
Error Messages
{
"type": "error",
"data": {
"code": "AUTH_FAILED",
"message": "Invalid or expired token"
}
}
Error Codes
| Code | Description |
|---|---|
AUTH_FAILED | Authentication failed |
INVALID_MESSAGE | Malformed message |
SUBSCRIPTION_ERROR | Invalid subscription request |
RATE_LIMITED | Too many messages |
Code Examples
JavaScript
const ws = new WebSocket('wss://bloqd.example.com/ws?token=f2b_your_api_key');
ws.onopen = () => {
console.log('Connected');
// Subscribe to events
ws.send(JSON.stringify({
action: 'subscribe',
events: ['ban', 'server_status']
}));
};
ws.onmessage = (event) => {
const message = JSON.parse(event.data);
switch (message.type) {
case 'ban':
console.log('New ban:', message.data);
break;
case 'server_status':
console.log('Server status:', message.data);
break;
case 'ping':
ws.send(JSON.stringify({ action: 'pong' }));
break;
}
};
ws.onclose = () => {
console.log('Disconnected');
};
Python
import asyncio
import websockets
import json
async def connect():
uri = "wss://bloqd.example.com/ws?token=f2b_your_api_key"
async with websockets.connect(uri) as ws:
# Subscribe
await ws.send(json.dumps({
"action": "subscribe",
"events": ["ban", "server_status"]
}))
async for message in ws:
data = json.loads(message)
if data["type"] == "ping":
await ws.send(json.dumps({"action": "pong"}))
elif data["type"] == "ban":
print(f"New ban: {data['data']}")
elif data["type"] == "server_status":
print(f"Server status: {data['data']}")
asyncio.run(connect())
Rate Limits
| Limit | Value |
|---|---|
| Max connections per API key | 5 |
| Max subscriptions per connection | 20 |
| Max messages per minute | 60 |
Best Practices
- Handle reconnection - Implement exponential backoff
- Respond to pings - Keep connection alive
- Subscribe selectively - Only subscribe to needed events
- Handle errors gracefully - Log and recover from errors
- Use secure connections - Always use wss://