WebSocket-based realtime stream of tweets, follow/unfollow events, profile changes, and new follower digests for the handles you monitor. Sub-second detection. TweetCatcher-compatible opcode framing.
OpenAPI spec · Postman collection
POST /v1/dt/targets or the bot's /add command.wss://api.xanguard.tech/v1/dt/realtime/ws and follow the opcode flow below.Frames are JSON objects with an op integer field. Some carry a d data field, events also carry a t type field.
| Code | Name | Direction | Purpose |
|---|---|---|---|
| 10 | HELLO | server → client | First frame after upgrade. d.heartbeat_interval is ms. |
| 2 | LOGIN | client → server | Reply to HELLO with {"op":2,"d":"YOUR_API_KEY"} within 15s. |
| 4 | READY | server → client | Auth succeeded. Streaming begins. |
| 0 | EVENT | server → client | Carries t + d. See event types below. |
| 1 | HEARTBEAT | client → server | Send every heartbeat_interval ms. |
| 11 | HEARTBEAT_ACK | server → client | Server's response to your heartbeat. |
| 3 | DISCONNECT | server → client | Connection closes after this frame. d is the reason string. |
Limits: 5 concurrent connections per API key. Stale events (>30s old) are dropped. Heartbeat ACK timeout is 90s.
New tweet, reply, quote, or retweet from a tracked handle.
{
"op": 0, "t": "tweet",
"d": {
"tweet_id": "1789...",
"author": {"handle": "elonmusk", "twitter_user_id": "44196397", "display_name": "Elon Musk", "avatar_url": "..."},
"text": "...",
"url": "https://x.com/elonmusk/status/1789...",
"is_reply": false, "is_quote": false, "is_retweet": false,
"image_urls": [], "mentions": [],
"created_at": "2026-05-09T11:23:45Z"
}
}
A tracked handle followed or unfollowed someone.
{
"op": 0, "t": "follow_change",
"d": {
"actor_handle": "elonmusk",
"target_handle": "naval",
"kind": "follow",
"detected_at": "2026-05-09T11:23:45Z"
}
}
A tracked handle changed bio, name, avatar, banner, pinned tweet, location, or website.
{
"op": 0, "t": "profile_change",
"d": {
"handle": "elonmusk",
"field": "bio",
"old_value": "...",
"new_value": "...",
"detected_at": "2026-05-09T11:23:45Z"
}
}
Digest of new followers for a tracked handle, emitted approximately every 30 minutes.
{
"op": 0, "t": "new_followers",
"d": {
"handle": "elonmusk",
"new_count": 42,
"new_followers": [
{"handle": "...", "twitter_user_id": "...", "display_name": "...", "follower_count": 12345}
],
"detected_at": "2026-05-09T11:23:45Z"
}
}
const ws = new WebSocket('wss://api.xanguard.tech/v1/dt/realtime/ws');
let heartbeat;
ws.onmessage = (raw) => {
const frame = JSON.parse(raw.data);
switch (frame.op) {
case 10: // HELLO
ws.send(JSON.stringify({ op: 2, d: 'dt_YOUR_API_KEY' })); // LOGIN
heartbeat = setInterval(
() => ws.send(JSON.stringify({ op: 1 })),
frame.d.heartbeat_interval
);
break;
case 4: console.log('streaming'); break; // READY
case 0: console.log(frame.t, frame.d); break; // EVENT
case 11: break; // HEARTBEAT_ACK
case 3: console.error('disconnected:', frame.d); break;
}
};
ws.onclose = () => clearInterval(heartbeat);
import asyncio, json
import websockets
async def stream():
async with websockets.connect('wss://api.xanguard.tech/v1/dt/realtime/ws') as ws:
hello = json.loads(await ws.recv()) # OP_HELLO
await ws.send(json.dumps({'op': 2, 'd': 'dt_YOUR_API_KEY'}))
heartbeat_ms = hello['d']['heartbeat_interval']
async def hb():
while True:
await asyncio.sleep(heartbeat_ms / 1000)
await ws.send(json.dumps({'op': 1}))
asyncio.create_task(hb())
async for raw in ws:
frame = json.loads(raw)
if frame['op'] == 0: # EVENT
print(frame['t'], frame['d'])
asyncio.run(stream())
| Method | Path | Purpose |
|---|---|---|
| GET | /v1/dt/targets | List tracked handles. |
| POST | /v1/dt/targets | Add handle: {"handle":"elonmusk"} |
| DELETE | /v1/dt/targets/{handle} | Stop tracking. |
| GET | /v1/dt/status | Subscription tier, expiry, slot usage. |
| PUT | /v1/dt/webhook | Set webhook URL (alternative delivery). |
All authenticate via ?api_key=dt_... query parameter. Full schemas in the OpenAPI spec.
If you'd rather receive HTTP POSTs than maintain a WS connection, set webhook_url:
curl -X PUT 'https://api.xanguard.tech/v1/dt/webhook?api_key=dt_...' \
-H 'Content-Type: application/json' \
-d '{"url":"https://your-server.example.com/xanguard"}'
Each delivery includes header X-Signature: <hex> = HMAC-SHA256(secret, raw_body). Verify on receive. Body shape:
{
"event": "tweet",
"timestamp": 1715253825000,
"data": { ... } // identical to the WS event "d" field
}
Retry: 3 attempts with 1s, 2s, 4s backoff. Auto-disable: 10 consecutive failures pause the URL until you re-set it.
| Code | Cause | Action |
|---|---|---|
| 401 | Missing/wrong/expired API key | Use /apikey in the bot to regenerate. |
| 403 | Free tier; account_limit exceeded | Upgrade plan. |
| 429 | Rate-limit exceeded (REST) or 5-conn cap (WS) | Back off; close idle connections. |
| OP_DISCONNECT | WS-level error; d is the reason | Reconnect with backoff. |
Questions: @0xDeep on Telegram. Bug reports preferred with payment_id + timestamp.