Documentation Index
Fetch the complete documentation index at: https://docs.xshot.fun/llms.txt
Use this file to discover all available pages before exploring further.
Connection
wss://api.xshot.fun/ws?api_key=YOUR_KEY
On connect, the server sends:
{
"type": "connected",
"timestamp": "2026-03-28T13:39:50.995Z"
}
Subscribe to a Channel
Send a JSON message:
{
"type": "subscribe",
"channel": "tweet:engagement",
"params": { "tweet_id": "2035548674483273831" },
"interval": 15
}
Server confirms:
{
"type": "subscribed",
"channel": "tweet:engagement",
"params": { "tweet_id": "2035548674483273831" },
"interval": 15
}
Receive Events
When data changes, the server pushes an event. Only changed fields are included — no event is sent if nothing changed.
Example — tweet gets 2 new views:
{
"type": "event",
"channel": "tweet:engagement",
"params": { "tweet_id": "2035548674483273831" },
"data": {
"view_count": 41836,
"view_count_delta": 2
},
"timestamp": "2026-03-28T13:40:14.239Z"
}
Unsubscribe
{
"type": "unsubscribe",
"channel": "tweet:engagement",
"params": { "tweet_id": "2035548674483273831" }
}
Server confirms:
{
"type": "unsubscribed",
"channel": "tweet:engagement",
"params": { "tweet_id": "2035548674483273831" }
}
Available Channels
| Channel | Description | Required Params | Default Interval | Min/Max |
|---|
user:tweets | New tweets from a user | username | 30s | 15-120s |
user:mentions | Tweets mentioning a user | username | 30s | 15-120s |
user:followers | Follower count changes | username | 60s | 30-300s |
tweet:engagement | Live likes, retweets, views | tweet_id | 15s | 10-120s |
search:tweets | New tweets matching a query | query | 30s | 15-120s |
New tweets from a specific user.
{
"type": "event",
"channel": "user:tweets",
"params": { "username": "elonmusk" },
"data": {
"new_tweets": [
{
"id": "2037850934274138146",
"text": "Starship launch window opens tomorrow",
"created_at": "Fri Mar 28 14:30:00 +0000 2026",
"author": {
"id": "44196397",
"name": "Elon Musk",
"username": "elonmusk",
"profile_image": "https://pbs.twimg.com/profile_images/.../normal.jpg",
"verified": false,
"followers_count": 237614000
},
"like_count": 45000,
"retweet_count": 8200,
"reply_count": 3100,
"view_count": 12000000
}
]
},
"timestamp": "2026-03-28T14:30:30.000Z"
}
user:mentions
New tweets mentioning a user.
{
"type": "event",
"channel": "user:mentions",
"params": { "username": "elonmusk" },
"data": {
"new_mentions": [
{
"id": "2037851000000000000",
"text": "@elonmusk when is the next Starship launch?",
"created_at": "Fri Mar 28 14:35:00 +0000 2026",
"author": {
"id": "999999999",
"name": "Space Fan",
"username": "spacefan42",
"profile_image": "https://pbs.twimg.com/profile_images/.../normal.jpg",
"verified": false,
"followers_count": 1500
},
"like_count": 5,
"retweet_count": 0,
"reply_count": 1,
"view_count": 200
}
]
},
"timestamp": "2026-03-28T14:35:30.000Z"
}
user:followers
Follower count changes. Reports the new count, previous count, and delta.
{
"type": "event",
"channel": "user:followers",
"params": { "username": "elonmusk" },
"data": {
"followers_count": 237614746,
"previous_count": 237614000,
"change": 746
},
"timestamp": "2026-03-28T14:31:00.000Z"
}
Live engagement metrics. Only changed fields are included, each with its delta.
{
"type": "event",
"channel": "tweet:engagement",
"params": { "tweet_id": "2035548674483273831" },
"data": {
"like_count": 328,
"like_count_delta": 2,
"view_count": 41836,
"view_count_delta": 985,
"retweet_count": 70,
"retweet_count_delta": 2
},
"timestamp": "2026-03-28T13:40:14.239Z"
}
New tweets matching a search query.
{
"type": "event",
"channel": "search:tweets",
"params": { "query": "bitcoin" },
"data": {
"new_tweets": [
{
"id": "2037852000000000000",
"text": "Bitcoin breaking through resistance levels today",
"created_at": "Fri Mar 28 15:00:00 +0000 2026",
"author": {
"id": "888888888",
"name": "Crypto Analyst",
"username": "cryptoanalyst",
"profile_image": "https://pbs.twimg.com/profile_images/.../normal.jpg",
"verified": false,
"followers_count": 50000
},
"like_count": 120,
"retweet_count": 30,
"reply_count": 15,
"view_count": 25000
}
]
},
"timestamp": "2026-03-28T15:00:30.000Z"
}
Error Events
Sent when polling fails (e.g. rate limit, account issues):
{
"type": "error",
"channel": "tweet:engagement",
"params": { "tweet_id": "2035548674483273831" },
"code": "POLL_ERROR",
"message": "Rate limited (429)"
}
Error codes: INVALID_JSON, INVALID_CHANNEL, SUBSCRIBE_FAILED, POLL_ERROR, UNKNOWN_TYPE
Keepalive
Send periodic pings to keep the connection alive:
The server also sends WebSocket-level pings every 30 seconds. Unresponsive clients are disconnected after 10 seconds.
Full JavaScript Example
const ws = new WebSocket("wss://api.xshot.fun/ws?api_key=YOUR_KEY");
ws.onopen = () => {
console.log("Connected to Xshot WebSocket");
// Monitor tweet engagement in real-time
ws.send(JSON.stringify({
type: "subscribe",
channel: "tweet:engagement",
params: { tweet_id: "2035548674483273831" },
interval: 15
}));
// Watch for new tweets from a user
ws.send(JSON.stringify({
type: "subscribe",
channel: "user:tweets",
params: { username: "elonmusk" },
interval: 30
}));
// Monitor follower count changes
ws.send(JSON.stringify({
type: "subscribe",
channel: "user:followers",
params: { username: "elonmusk" },
interval: 60
}));
};
ws.onmessage = (event) => {
const msg = JSON.parse(event.data);
switch (msg.type) {
case "connected":
console.log("Server ready:", msg.timestamp);
break;
case "subscribed":
console.log(`Subscribed to ${msg.channel} (polling every ${msg.interval}s)`);
break;
case "event":
console.log(`[${msg.channel}]`, JSON.stringify(msg.data, null, 2));
break;
case "error":
console.error(`Error on ${msg.channel}: ${msg.message}`);
break;
}
};
ws.onclose = (event) => {
if (event.code === 4001) {
console.error("Authentication failed - check your API key");
} else {
console.log("Disconnected:", event.code, event.reason);
}
};
Full Python Example
import asyncio
import json
import websockets
API_KEY = "YOUR_KEY"
async def main():
uri = f"wss://api.xshot.fun/ws?api_key={API_KEY}"
async with websockets.connect(uri) as ws:
# Subscribe to follower changes
await ws.send(json.dumps({
"type": "subscribe",
"channel": "user:followers",
"params": {"username": "elonmusk"},
"interval": 60
}))
async for message in ws:
msg = json.loads(message)
if msg["type"] == "event":
data = msg["data"]
print(f"Followers: {data['followers_count']} ({data['change']:+d})")
elif msg["type"] == "error":
print(f"Error: {msg['message']}")
asyncio.run(main())
Behavior Details
- Deduplication: Multiple clients on the same resource share one poll
- First poll: Captures initial snapshot without emitting events (avoids flood)
- Auto-cleanup: Polling stops when all clients unsubscribe from a resource
- Max subscriptions: 100 total across all connected clients
- Snapshot cap: 500 IDs per subscription to prevent memory growth
- Error backoff: After 5 consecutive poll failures, an error event is sent to all subscribers