Xanguard Documentation

Build on top of the fastest Twitter monitoring engine available. Detect tweets in real-time with sub-second latency and deliver them to your app, bot, or trading system through the channel that fits your stack.

What is Xanguard?

Xanguard is a real-time Twitter monitoring platform. It uses a proprietary detection engine to discover new tweets the moment they appear, delivering alerts in typically 250–500ms. Latency varies based on account follower count and tweet complexity.

Whether you are a crypto trader watching influencer wallets, a DeFi protocol monitoring your team accounts, or an AI agent consuming social signals, Xanguard gives you the infrastructure to react before anyone else.

Four Delivery Channels

Telegram Bot

Instant notifications in private chats or organized forum topics. No code required. Add handles with a single command and start receiving alerts.

REST API

15 endpoints to manage accounts, settings, subscriptions, and webhooks programmatically. Standard JSON request/response with Bearer token auth.

WebSocket Streaming

Persistent connection for real-time tweet delivery. Subscribe to handles on the fly and receive structured JSON alerts as they happen.

Signed Webhooks

HMAC-SHA256 signed POST requests to your HTTPS endpoint. Automatic retries with exponential backoff. Zero polling on your end.

Quick Start

Xanguard is an API-first, real-time Twitter/X firehose. Get from zero to a live event stream in four steps.

1

Onboard

Open @B2B_Xanguard_bot on Telegram, send /start, and choose a plan (priced by handle count — see B2B Pricing).

2

Get your API key

Send /apikey to receive a key with the dt_ prefix. Base URL is https://api.xanguard.tech/v1/dt. Authenticate every REST call with a Bearer header:

Authorization: Bearer dt_your_api_key_here
3

Add a handle

Register an account to monitor. Every response uses the envelope {"ok":true,"data":…} (or {"ok":false,"error":"…"} on failure).

curl -X POST https://api.xanguard.tech/v1/dt/targets \
  -H "Authorization: Bearer dt_your_api_key_here" \
  -H "Content-Type: application/json" \
  -d '{"handle":"elonmusk"}'

# → 201 {"ok":true,"data":{"handle":"elonmusk","twitter_user_id":"44196397"}}
4

Stream events

Connect the WebSocket, send the LOGIN opcode with your dt_ key, and receive real-time events for every monitored handle. See B2B Realtime WebSocket for the full protocol.

wss://api.xanguard.tech/v1/dt/realtime/ws

Prefer chat delivery, or looking for the consumer Tweet-Alerts bot? See the Telegram Bot section below.


Telegram Bot

The Telegram bot is the easiest way to use Xanguard. It works in private chats and in groups. In groups with forum topics enabled, the bot automatically creates a dedicated topic thread for each tracked handle, keeping your notifications organized.

Commands

/start Register your account and view available subscription plans. This is the entry point for new users.
/add handle1 handle2 ... Quick-add one or more Twitter handles to your monitoring list. Separate handles with spaces. No @ prefix needed.
/monitor Open the interactive account management flow. Add, import, view, and manage your tracked accounts through inline buttons.
/setup Configure a Telegram group for notifications. Enables forum topic auto-creation so each handle gets its own thread.
/settings Toggle notification filters: exclude replies, exclude reposts, contracts only mode, auto topics, contract topic routing, and pause all notifications.
/help Show the command reference and support information.
/apikey Generate or view your REST API key. Use this key for API, WebSocket, and webhook authentication.
/referral Manage your referral link and set your payout wallet.
/plans View all pricing plans.

Features

Forum Topics

When you add the bot to a Telegram group with forum topics enabled, it automatically creates a dedicated topic thread for each tracked Twitter handle. All tweets from that handle are routed to their respective topic, keeping your group organized and easy to follow.

Contract Detection

Xanguard automatically detects Solana and Ethereum contract addresses embedded in tweets. When a tweet contains a contract address, it is flagged in the notification. You can enable contracts only mode in settings to receive only tweets that contain contract addresses.

Keyword Filtering

Set per-handle keyword filters so that only tweets matching at least one of your keywords trigger an alert. This is useful for high-volume accounts where you only care about specific topics. Manage keywords through the per-account detail screen in /monitor or via the REST API.

Mute / Unmute

Temporarily mute individual accounts without removing them from your list. Muted accounts retain their keywords and configuration but will not trigger any notifications until you unmute them.


REST API

The REST API exposes 15 endpoints for managing your Xanguard account programmatically. All endpoints live under a single base URL and return consistent JSON responses.

Base URL
https://api.xanguard.tech/v1

Authentication

All API requests require a Bearer token in the Authorization header. Generate your API key by sending /apikey to the Telegram bot.

Authorization Header
Authorization: Bearer xg_your_api_key_here

The server hashes your key with SHA-256 and looks it up in the api_keys table, joining on your subscription tier to determine rate limits and permissions.

Response Envelope

Every response is wrapped in a standard envelope. On success, the ok field is true and the payload is in data. On error, ok is false and the error message is in error.

JSON — Success response
{
  "ok": true,
  "data": { ... }
}
JSON — Error response
{
  "ok": false,
  "error": "Invalid API key"
}

Rate Limiting

Requests are rate-limited using a per-key sliding window. The limit is determined by your subscription tier (the ws_rate_limit_rps field on your tier). When you exceed the limit, the API returns 429 Too Many Requests.

Accounts

Manage your tracked Twitter accounts. Add, remove, configure keywords, and mute/unmute handles.

Method Path Description
GET /v1/accounts List all tracked accounts
POST /v1/accounts Add accounts (max 25 per request)
GET /v1/accounts/{handle} Get account detail + profile data
DELETE /v1/accounts/{handle} Remove an account
PUT /v1/accounts/{handle}/keywords Set keyword filters (max 20)
DELETE /v1/accounts/{handle}/keywords Clear all keywords
PUT /v1/accounts/{handle}/mute Mute or unmute an account
PATCH /v1/accounts/{handle}/filters Set per-account notification filters (exclude replies/reposts, contracts-only, etc.)
GET /v1/accounts

Returns all Twitter accounts you are currently monitoring, along with their keyword filters and mute status.

Response

JSON
{
  "ok": true,
  "data": {
    "accounts": [
      {
        "handle": "elonmusk",
        "keywords": [],
        "muted": false,
        "added_at": 1234567890
      }
    ],
    "count": 1,
    "limit": 10
  }
}
POST /v1/accounts

Add one or more Twitter handles to your monitoring list. Maximum 25 handles per request. Handles are case-insensitive and the @ prefix is optional.

Request Body

JSON
{
  "handles": ["elonmusk", "VitalikButerin"]
}

Response

JSON
{
  "ok": true,
  "data": {
    "added": ["elonmusk"],
    "already_exists": ["vitalikbuterin"],
    "total": 5,
    "limit": 10
  }
}
GET /v1/accounts/{handle}

Get detailed information about a single tracked account, including profile data fetched from Twitter (display name, follower count, verification status, and profile picture).

Response

JSON
{
  "ok": true,
  "data": {
    "handle": "elonmusk",
    "keywords": ["bitcoin", "doge"],
    "muted": false,
    "added_at": 1234567890,
    "profile": {
      "display_name": "Elon Musk",
      "followers": 180000000,
      "is_verified": true,
      "profile_pic": "https://pbs.twimg.com/..."
    }
  }
}
DELETE /v1/accounts/{handle}

Remove a Twitter handle from your monitoring list. This also removes any keyword filters associated with the handle.

Response

JSON
{
  "ok": true,
  "data": {
    "removed": "elonmusk",
    "total": 4,
    "limit": 10
  }
}
PUT /v1/accounts/{handle}/keywords

Set keyword filters for a specific account. Only tweets containing at least one of the specified keywords will trigger an alert. Maximum 20 keywords. This replaces any existing keywords.

Request Body

JSON
{
  "keywords": ["bitcoin", "solana", "launch"]
}

Response

JSON
{
  "ok": true,
  "data": {
    "handle": "elonmusk",
    "keywords": ["bitcoin", "solana", "launch"]
  }
}
DELETE /v1/accounts/{handle}/keywords

Clear all keyword filters for a specific account. After clearing, all tweets from this account will trigger alerts (subject to global settings).

Response

JSON
{
  "ok": true,
  "data": {
    "handle": "elonmusk",
    "keywords": []
  }
}
PUT /v1/accounts/{handle}/mute

Mute or unmute a tracked account. Muted accounts remain in your list but do not trigger any notifications.

Request Body

JSON
{
  "muted": true
}

Response

JSON
{
  "ok": true,
  "data": {
    "handle": "elonmusk",
    "muted": true
  }
}

Settings

Manage your global notification preferences. These settings apply to all delivery channels.

Method Path Description
GET /v1/settings Get current notification preferences
PATCH /v1/settings Update preferences (partial update)

Settings Fields

All fields are booleans. The PATCH endpoint accepts partial updates — only include the fields you want to change.

exclude_replies false Skip tweets that are replies to other users.
contracts_only false Only deliver tweets that contain a detected contract address (Solana or ETH).
notifications_paused false Pause all notifications across every delivery channel.
exclude_reposts false Skip repost/retweet tweets.
auto_topics true Automatically create a forum topic in your Telegram group for each tracked handle.
contract_topic false Route tweets containing contract addresses to a dedicated "Contracts" forum topic.
GET /v1/settings

Returns your current notification preferences.

Response

JSON
{
  "ok": true,
  "data": {
    "exclude_replies": false,
    "contracts_only": false,
    "notifications_paused": false,
    "exclude_reposts": false,
    "auto_topics": true,
    "contract_topic": false
  }
}
PATCH /v1/settings

Update one or more notification settings. Only include the fields you want to change. Omitted fields remain unchanged.

Request Body

JSON
{
  "exclude_replies": true,
  "contracts_only": true
}

Response

Returns the full settings object after the update.

JSON
{
  "ok": true,
  "data": {
    "exclude_replies": true,
    "contracts_only": true,
    "notifications_paused": false,
    "exclude_reposts": false,
    "auto_topics": true,
    "contract_topic": false
  }
}

Subscription

View your current subscription tier and browse available plans.

Method Path Description
GET /v1/subscription Current tier, limits, and expiry
GET /v1/plans List all available plans
GET /v1/subscription

Returns your current subscription tier, account limit, and expiration date.

Response

JSON
{
  "ok": true,
  "data": {
    "tier": "starter",
    "account_limit": 10,
    "expires_at": "2026-03-21T00:00:00Z"
  }
}
GET /v1/plans

Returns all available subscription plans with their prices, account limits, and webhook limits.

Response

JSON
{
  "ok": true,
  "data": {
    "plans": [
      {
        "name": "Free",
        "price_usd": 0,
        "account_limit": 2,
        "max_webhooks": 0
      },
      {
        "name": "Starter",
        "price_usd": 19,
        "account_limit": 10,
        "max_webhooks": 1
      }
    ]
  }
}

Webhooks

Register HTTPS endpoints to receive tweet notifications via signed POST requests. The number of webhooks you can register depends on your subscription tier.

Method Path Description
POST /v1/webhooks Register a new webhook (HTTPS only)
GET /v1/webhooks List active webhooks
DELETE /v1/webhooks/{id} Deactivate a webhook
POST /v1/webhooks

Register a new webhook endpoint. The URL must use HTTPS. On success, the response includes a one-time secret field containing the HMAC-SHA256 signing key. Save this immediately — it is never shown again.

Request Body

JSON
{
  "url": "https://your-server.com/webhook",
  "events": ["tweet"],
  "filter_handles": [],
  "filter_keywords": []
}

Tip: Leave filter_handles empty to receive tweets from all your tracked accounts. Leave filter_keywords empty to receive all tweets without keyword filtering.

Response

JSON
{
  "ok": true,
  "data": {
    "id": "wh_a1b2c3d4",
    "url": "https://your-server.com/webhook",
    "events": ["tweet"],
    "secret": "whsec_k9x8m7...",
    "active": true
  }
}

Important: The secret field is only returned once, at creation time. Store it securely. You will need it to verify webhook signatures.

GET /v1/webhooks

List all your registered webhooks. The secret is not included in list responses.

Response

JSON
{
  "ok": true,
  "data": {
    "webhooks": [
      {
        "id": "wh_a1b2c3d4",
        "url": "https://your-server.com/webhook",
        "events": ["tweet"],
        "active": true
      }
    ],
    "count": 1,
    "limit": 5
  }
}
DELETE /v1/webhooks/{id}

Deactivate a webhook. It will stop receiving deliveries immediately.

Response

JSON
{
  "ok": true,
  "data": {
    "id": "wh_a1b2c3d4",
    "deactivated": true
  }
}

Webhook Delivery

When a tweet matches your filters, Xanguard sends a POST request to your registered URL with a JSON body containing the tweet data.

Signature Verification

Every delivery includes an X-Xanguard-Signature header containing an HMAC-SHA256 hex digest of the request body, computed using your webhook secret. Always verify this signature before processing the payload.

JavaScript — Verify Signature
const crypto = require('crypto');

function verifySignature(body, signature, secret) {
  const expected = crypto
    .createHmac('sha256', secret)
    .update(body)
    .digest('hex');
  return crypto.timingSafeEqual(
    Buffer.from(expected),
    Buffer.from(signature)
  );
}
Python — Verify Signature
import hmac, hashlib

def verify_signature(body: bytes, signature: str, secret: str) -> bool:
    expected = hmac.new(
        secret.encode(), body, hashlib.sha256
    ).hexdigest()
    return hmac.compare_digest(expected, signature)

Retry Policy

If your endpoint returns a non-2xx status code or the request times out, Xanguard retries up to 3 times with exponential backoff: 1 second, 2 seconds, then 4 seconds. After 10 consecutive failures across any deliveries, the webhook is automatically disabled. You can re-register it via the API once your endpoint is healthy again.


WebSocket

The WebSocket endpoint provides a persistent, real-time stream of tweet alerts. Connect once, subscribe to handles on the fly, and receive structured JSON messages as tweets happen. This is ideal for trading bots, dashboards, and any application that needs the lowest possible latency.

Connection

Connect with your API key as a query parameter:

WebSocket URL
wss://api.xanguard.tech/v1/ws?api_key=xg_your_key

Client to Server Messages

After connecting, send JSON messages to subscribe or unsubscribe from handles:

JSON — Subscribe to handles
{
  "type": "subscribe",
  "handles": ["elonmusk", "VitalikButerin"]
}
JSON — Unsubscribe from handles
{
  "type": "unsubscribe",
  "handles": ["elonmusk"]
}

Server to Client Messages

Tweet Alert

Received when a tracked account posts a tweet:

JSON — Tweet alert
{
  "type": "alert",
  "handle": "elonmusk",
  "text": "Just bought more $BTC",
  "url": "https://twitter.com/elonmusk/status/123",
  "tweet_id": "123",
  "timestamp": 1234567890
}

Acknowledgement

Sent after a successful subscribe or unsubscribe action:

JSON — Acknowledgement
{
  "type": "ack",
  "action": "subscribe",
  "handles": ["elonmusk"],
  "active": 1,
  "max": 25
}

Error

Sent when a request cannot be fulfilled:

JSON — Error
{
  "type": "error",
  "message": "Max handles exceeded"
}

Keepalive

The server sends a WebSocket ping frame every 30 seconds and expects a pong response within 10 seconds. Most WebSocket libraries handle this automatically. If the pong is not received, the server closes the connection. Your client should implement automatic reconnection with backoff.

Example: JavaScript Client

JavaScript — WebSocket client
const ws = new WebSocket(
  'wss://api.xanguard.tech/v1/ws?api_key=xg_your_key'
);

ws.onopen = () => {
  // Subscribe to handles once connected
  ws.send(JSON.stringify({
    type: 'subscribe',
    handles: ['elonmusk', 'VitalikButerin']
  }));
};

ws.onmessage = (event) => {
  const msg = JSON.parse(event.data);

  if (msg.type === 'alert') {
    console.log(`Tweet from @${msg.handle}: ${msg.text}`);
    console.log(`Link: ${msg.url}`);
  }

  if (msg.type === 'ack') {
    console.log(`Watching ${msg.active}/${msg.max} handles`);
  }

  if (msg.type === 'error') {
    console.error(`Error: ${msg.message}`);
  }
};

ws.onclose = () => {
  // Implement reconnection with backoff
  console.log('Disconnected, reconnecting...');
};

Example: Python Client

Python — WebSocket client (asyncio)
import asyncio, json, websockets

async def main():
    uri = "wss://api.xanguard.tech/v1/ws?api_key=xg_your_key"

    async with websockets.connect(uri) as ws:
        # Subscribe to handles
        await ws.send(json.dumps({
            "type": "subscribe",
            "handles": ["elonmusk", "VitalikButerin"]
        }))

        async for message in ws:
            msg = json.loads(message)

            if msg["type"] == "alert":
                print(f"@{msg['handle']}: {msg['text']}")
                print(f"Link: {msg['url']}")

asyncio.run(main())

Community Watch

Community Watch (CW) is a separate Xanguard product that monitors Twitter community gate activity in real time. It detects when any tracked account creates, joins, or leaves a Twitter community, and delivers alerts via webhook or the Telegram bot @F_xanguard_bot.

Separate from Xanguard tweet alerts. CW has its own bot, subscription, and API. You don't need a Xanguard subscription to use CW, and vice versa.

How It Works

  1. Subscribe via @F_xanguard_bot — pick a plan based on how many accounts you want to track.
  2. Add targets — tell the bot which Twitter accounts to monitor (e.g. @elonmusk).
  3. Get alerts — within ~30 seconds of a community join/leave/create, you get a notification via your configured webhook or the Telegram bot.

On first add, you'll receive a one-time sync of all communities the target is already in. After that, only changes trigger alerts.

Bot Commands

CommandDescription
/startDashboard & subscription page
/addAdd target account(s)
/removeRemove a target
/listList tracked targets
/statusCurrent subscription status, handles tracked, expiry
/apikeyView or regenerate your CW API key
/settingsConfigure filters (event types, member count, flap cooldown)
/helpCommand reference and quick-start guide

Filters

CW supports per-client filters to reduce noise. Configure them via /settings in the bot or the API.

FilterDefaultDescription
Event TypesAll (join, leave, create, rename, description, follow)Choose which events trigger alerts. E.g. only "join" and "follow" events.
Min Member Count0Ignore communities with fewer members than this threshold.
Flap Cooldown0sIf a target joins and leaves the same community within this window, suppress the leave event. Useful to filter bots.

CW API & Webhooks

CW has its own REST API and webhook delivery system, separate from the main Xanguard API.

Authentication

All CW API requests require your CW API key (generated via /apikey in the bot). Pass it as a header:

Authorization: Bearer cw_your_api_key_here

Base URL: https://api.xanguard.tech/v1/cw

Endpoints

MethodEndpointDescription
GET/v1/cw/targetsList all monitored accounts
POST/v1/cw/targetsAdd accounts to monitor. Body: {"handles": ["elonmusk", "vitalik"]}
DELETE/v1/cw/targets/{handle}Remove a target
GET/v1/cw/webhookGet configured webhook URL
PUT/v1/cw/webhookSet webhook URL
GET/v1/cw/settingsGet current filter settings
PATCH/v1/cw/settingsUpdate filter settings
GET/v1/cw/statusSubscription status, handles tracked, expiry
WS/v1/cw/wsWebSocket stream of CW events

Webhook Format

Configure your webhook URL via /settings in the bot. CW sends a POST request for each event:

{
  "event": "community_joined",
  "screen_name": "elonmusk",
  "twitter_user_id": "44196397",
  "community": {
    "id": "1234567890",
    "name": "Crypto Builders",
    "member_count": 15420
  },
  "detected_at": "2026-03-03T15:30:00Z"
}

Event types: community_joined, community_left, community_created, community_renamed, community_description_changed, account_followed


CW Pricing

Community Watch is billed monthly in SOL. Subscribe via @F_xanguard_bot.

PlanAccountsPrice
CW 2020$100/mo
CW 5050$250/mo
CW 100100$500/mo
CW 200200$800/mo
CW 250250$1,000/mo
CW 500500$1,500/mo

Add-ons

Add-onTierPrice
Community Posts Scanner5 communities$50/mo
Community Posts Scanner10 communities$90/mo
Community Posts Scanner20 communities$160/mo
Community Rename watchUp to 25 communities (name/description changes)$40/mo

Upgrades are prorated — you only pay the difference for the remaining days. Renewals stack from your current expiry date.

Payment is in SOL. The exact SOL amount is calculated at checkout based on current SOL/USD rate.


Convergence Tracker

Convergence Tracker (CT) detects when multiple tracked Twitter accounts cluster in the same community simultaneously. When 2+ targets appear in one community, CT fires a convergence alert — a strong signal that a coordinated token launch or community event may be imminent. Managed via @T_Xanguard_bot.

Requires Community Watch data. CT uses CW’s detection infrastructure. You don’t need a CW subscription yourself — CT handles it internally.

Bot Commands

CommandDescription
/startDashboard & subscription
/add @handleAdd a target for convergence tracking
/remove @handleRemove a target
/listList all tracked targets
/apikeyView or regenerate your CT API key
/helpCommand reference

Pricing

PlanTargetsPrice
CT 2020$100/mo
CT 5050$250/mo
CT 100100$500/mo
CT 200200$800/mo
CT 500500$1,500/mo

CT API

All CT API requests require a Bearer token with ct_ prefix, generated via /apikey in the bot.

Authorization: Bearer ct_your_api_key_here

Endpoints

MethodPathDescription
GET/v1/ct/targetsList tracked targets
POST/v1/ct/targetsAdd target. Body: {"handle": "username"}
DELETE/v1/ct/targets/{handle}Remove target
GET/v1/ct/convergenceCurrent convergence detections
GET/v1/ct/convergence/historyHistorical convergence events
GET/v1/ct/settingsGet CT settings (min_convergence, time_window)
PATCH/v1/ct/settingsUpdate settings
GET/v1/ct/webhookGet webhook URL
PUT/v1/ct/webhookSet webhook URL. Body: {"url": "https://..."}
GET/v1/ct/statusSubscription status

WebSocket

wss://api.xanguard.tech/v1/ct/ws?api_key=ct_your_key

Receives real-time JSON events when convergence is detected.


Xanguard B2B

Xanguard B2B is a real-time Twitter/X monitoring API. It streams tweets, deleted-tweet alerts, follow/unfollow events, profile changes, and new follower detection for your tracked accounts via WebSocket and REST API. Managed via @B2B_Xanguard_bot.

Modules

ModuleEvents
Realtime (tweets)New tweets, replies, quotes, retweets
Deleted tweetsAlert when a tracked account deletes a tweet
FollowsFollow and unfollow detection
Profile WatchName, bio, avatar, follower count changes
FollowersNew follower detection

Bot Commands

CommandDescription
/startDashboard & subscription
/add @handleAdd handle to monitor
/remove @handleRemove handle
/listList all monitored handles
/statusSubscription status
/apikeyView or regenerate API key
/helpCommand reference

Pricing

Three module tiers, priced by handle count (monthly):

HandlesStarter
tweets + deleted-tweet
Pro
+ profile + new-follower
Enterprise
+ follow/unfollow
50$49/mo$99/mo$249/mo
250$229/mo$429/mo$979/mo
500$449/mo$749/mo$1,649/mo
1000$849/mo$1,349/mo$2,849/mo

B2B API

All B2B API requests require a Bearer token with dt_ prefix, generated via /apikey in the bot.

Authorization: Bearer dt_your_api_key_here

REST Endpoints

MethodPathDescription
GET/v1/dt/targetsList monitored handles
POST/v1/dt/targetsAdd handle. Body: {"handle": "username"}
DELETE/v1/dt/targets/{handle}Remove handle
GET/v1/dt/profile/{handle}Latest profile snapshot
GET/v1/dt/profile/{handle}/historyProfile change history
GET/v1/dt/tweets/{handle}Recent tweets
GET/v1/dt/following/{handle}Accounts the handle follows
GET/v1/dt/followers/{handle}The handle's followers
GET/v1/dt/communities/{handle}Communities the handle belongs to
GET/v1/dt/social/diff/{handle}Follow/unfollow diff over a trailing window
GET/v1/dt/webhookGet webhook URL
PUT/v1/dt/webhookSet webhook URL
GET/v1/dt/statusSubscription status

Every response uses the standard envelope: {"ok":true,"data":…} on success, {"ok":false,"error":"…"} on failure. All examples below omit the outer envelope where noted.

POST /v1/dt/targets — add a handle

Resolves the handle against Twitter, stores its numeric ID, and starts monitoring. Idempotent per handle.

Request:  {"handle": "elonmusk"}

201 Created:
{"ok":true,"data":{"handle":"elonmusk","twitter_user_id":"44196397"}}

Errors: 400 "handle is required" · 403 "Handle limit reached (N/M)" · 409 "@elonmusk is already tracked" · 404 "@elonmusk not found on Twitter" · 502 "Failed to resolve @elonmusk" · 503 upstream/scrape temporarily unavailable.

GET /v1/dt/targets — list handles

Returns your monitored handles and your plan's handle ceiling.

{
  "ok": true,
  "data": {
    "targets": [
      {"id": 42, "screen_name": "elonmusk", "twitter_user_id": "44196397", "is_active": true, "created_at": "2026-07-01T12:00:00Z"}
    ],
    "count": 1,
    "max_handles": 500
  }
}

DELETE /v1/dt/targets/{handle} — remove a handle

{"ok":true,"data":{"removed":"elonmusk"}}

Returns 404 "@elonmusk not found" if the handle is not in your set.

GET /v1/dt/status — subscription status

Current handle usage, active state, days remaining, and enabled modules.

{
  "ok": true,
  "data": {
    "targets": 137,
    "max_handles": 500,
    "is_active": true,
    "days_left": 24,
    "modules": ["realtime", "follows", "profile_watch"]
  }
}

GET /v1/dt/profile/{handle} — latest profile snapshot

Most recent stored profile for a monitored handle. Returns 404 "No profile data for @handle yet" until the first scrape completes.

{
  "ok": true,
  "data": {
    "twitter_id": "44196397",
    "screen_name": "elonmusk",
    "display_name": "Elon Musk",
    "bio": "…",
    "location": "…",
    "website": "…",
    "followers": 190000000,
    "following": 800,
    "tweet_count": 42000,
    "likes_count": 30000,
    "listed_count": 150000,
    "media_count": 5000,
    "is_blue_verified": true,
    "verified_type": null,
    "avatar_url": "https://pbs.twimg.com/profile_images/…",
    "banner_url": "https://pbs.twimg.com/profile_banners/…",
    "account_created_at": "2009-06-02T20:12:29Z",
    "scraped_at": "2026-07-04T09:15:00Z"
  }
}

GET /v1/dt/profile/{handle}/history — profile change history

Time series of follower / following / tweet / like / listed counts, newest first. Query params: limit (default 50, max 200), offset (default 0).

{
  "ok": true,
  "data": {
    "history": [
      {"followers": 190000000, "following": 800, "tweet_count": 42000, "likes_count": 30000, "listed_count": 150000, "scraped_at": "2026-07-04T09:15:00Z"}
    ],
    "count": 1
  }
}

GET /v1/dt/tweets/{handle} — recent tweets

Capped at the last 20 tweets captured by the detection layer (no pagination, no since). Note: engagement metrics (likes, retweets, replies, quotes, views, bookmarks) are returned as 0 and full media metadata (media_types, video_urls) is not populated on this endpoint. For complete tweet objects with media and enrichment, use the realtime WebSocket.

{
  "ok": true,
  "data": {
    "tweets": [
      {
        "tweet_id": "1234567890123456789",
        "full_text": "Hello world",
        "created_at": "2026-07-04T09:14:00Z",
        "source": "bgp",
        "likes": 0, "retweets": 0, "replies": 0, "quotes": 0, "views": 0, "bookmarks": 0,
        "is_retweet": false, "is_reply": false, "is_quote": false,
        "media_urls": ["https://pbs.twimg.com/media/…"],
        "mentions": ["vitalikbuterin"]
      }
    ],
    "count": 1
  }
}

GET /v1/dt/following/{handle} & /v1/dt/followers/{handle}

The accounts a handle follows, or its followers. Query params: limit (default 100, max 500), offset (default 0). The response key is following or followers respectively; total is the full graph size.

GET /v1/dt/following/elonmusk
{
  "ok": true,
  "data": {
    "following": [
      {"target_id": "44196397", "target_screen_name": "vitalikbuterin", "is_current": true, "first_seen_at": "2026-06-01T00:00:00Z", "last_seen_at": "2026-07-04T00:00:00Z"}
    ],
    "count": 1,
    "total": 800
  }
}

GET /v1/dt/communities/{handle} — communities

{
  "ok": true,
  "data": {
    "communities": [
      {"community_id": "1493446837214187523", "community_name": "Build in Public", "member_count": 120000, "creator_screen_name": "someuser", "is_current": true, "first_seen_at": "2026-06-01T00:00:00Z", "last_seen_at": "2026-07-04T00:00:00Z"}
    ],
    "count": 1
  }
}

GET /v1/dt/social/diff/{handle} — follow / unfollow diff

This is how you detect unfollows. There is no real-time unfollow event — poll this endpoint. It returns follows added and removed over a trailing 7-day window (up to 100 of each, newest first).

{
  "ok": true,
  "data": {
    "added": [
      {"target_id": "44196397", "target_screen_name": "vitalikbuterin", "relation": "following", "change": "added", "changed_at": "2026-07-03T10:00:00Z"}
    ],
    "removed": [
      {"target_id": "888", "target_screen_name": "someone", "relation": "following", "change": "removed", "changed_at": "2026-07-02T18:00:00Z"}
    ],
    "added_count": 1,
    "removed_count": 1
  }
}

GET /v1/dt/webhook & PUT /v1/dt/webhook

GET returns your configured callback URL and whether a signing secret is set (the secret itself is never returned by GET). PUT sets the URL (HTTPS only), rotates the signing secret, and returns it once.

GET  /v1/dt/webhook
{"ok":true,"data":{"url":"https://your-server.com/webhook","has_secret":true}}

PUT  /v1/dt/webhook   Request: {"url":"https://your-server.com/webhook"}
{"ok":true,"data":{"url":"https://your-server.com/webhook","secret":"3f9a1c…","note":"Store this secret securely."}}

Delivery channel: B2B events are streamed live over the Realtime WebSocket — that is the primary, always-on B2B delivery path. These endpoints store an optional signed-webhook URL for accounts with webhook push enabled.

When a signed delivery is sent, it carries an X-Signature header: a lowercase HMAC-SHA256 hex digest of the raw request body, keyed with the secret returned by PUT. Verify it exactly like the consumer webhook (identical scheme) before trusting the payload:

import hmac, hashlib

def verify_signature(body: bytes, signature: str, secret: str) -> bool:
    expected = hmac.new(secret.encode(), body, hashlib.sha256).hexdigest()
    return hmac.compare_digest(expected, signature)  # signature = X-Signature header

REST Error Codes

Failures return {"ok":false,"error":"…"} with the HTTP status below.

StatusMeaningExample error
400Bad request — missing/invalid field"handle is required"
401Auth failed — missing / malformed / invalid dt_ key"Invalid or inactive API key"
403Handle ceiling reached for your plan"Handle limit reached (500/500)"
404Handle not found on Twitter, not tracked, or no data yet"@handle not found on Twitter"
409Handle already in your monitored set"@handle is already tracked"
502Upstream resolve failed"Failed to resolve @handle"
503Service / scrape / B2B database temporarily unavailable"Service temporarily unavailable"

Limits: REST requests are not per-second rate-limited, but the enforced limits are your plan's handle ceiling (max_handles403), a 64 KB request-body cap, and 5 concurrent WebSocket connections per key. High-volume consumers should use the WebSocket rather than polling REST.

Realtime WebSocket

wss://api.xanguard.tech/v1/dt/realtime/ws

TweetCatcher-compatible opcode protocol. Connect, send the LOGIN opcode with your dt_ API key, and receive real-time events for all monitored handles. See B2B Realtime WebSocket below for the full opcode table, handshake flow, and every event payload.


B2B Realtime WebSocket

High-volume real-time feed with TweetCatcher-compatible opcode protocol. Delivers tweets, follow detection, profile changes, and new follower alerts via a single WebSocket connection. Managed via @B2B_Xanguard_bot.

Connection

wss://api.xanguard.tech/v1/dt/realtime/ws

No query parameter needed — authentication happens via the LOGIN opcode after connecting. Maximum 5 concurrent WebSocket connections per API key.

Opcodes

OpcodeNameDirectionDescription
10HELLOServer → ClientSent on connect. Includes heartbeat_interval (ms).
2LOGINClient → ServerSend your dt_ API key to authenticate. Must be sent within 15 seconds.
4READYServer → ClientAuth successful. Includes client_id, modules, handles count.
0EVENTServer → ClientRealtime event data.
1HEARTBEATClient → ServerKeep-alive. Send every heartbeat_interval ms.
11HEARTBEAT_ACKServer → ClientResponse to heartbeat.
3DISCONNECTServer → ClientConnection terminated with reason.

Handshake Flow

1. Connect → Receive HELLO:

{"op": 10, "d": {"heartbeat_interval": 30000}}

2. Send LOGIN with your API key:

{"op": 2, "d": "dt_your_api_key_here"}

3. Receive READY on success:

{"op": 4, "d": {"client_id": 1, "modules": ["realtime", "follows", "profile_watch", "followers"], "handles": 150, "max_handles": 1000}}

4. Send a HEARTBEAT ({"op": 1}) every heartbeat_interval ms (30s). The server replies with HEARTBEAT_ACK (op 11). If it receives no heartbeat for 90 seconds (3 missed intervals) it drops the connection with a DISCONNECT.

Modules

Modules are configured per client. You only receive events for enabled modules.

ModuleEventsDescription
realtimetwitter.post.new, twitter.post.update, twitter.tweet.deletedTweets, replies, quotes, retweets in real-time. Initial delivery via twitter.post.new, enriched re-delivery via twitter.post.update. + deleted-tweet alerts.
followstwitter.following.new, twitter.following.removedWhen a tracked account follows or unfollows someone (~30-60s detection)
profile_watchtwitter.profile.updateBio, name, avatar, pinned tweet changes (~500ms detection)
followerstwitter.follower.newNew followers of tracked accounts (~30min digest)

Delivery semantics: the stream is real-time only — events for tweets older than 30 seconds are dropped (no backfill on connect). Deleted-tweet (twitter.tweet.deleted) and new-follower (twitter.follower.new) events additionally require a per-account opt-in flag; enabling the module alone does not deliver them — ask us to enable deletes / followers on your account.

Event: twitter.post.new

First delivery of a detected tweet — the fastest event, and it carries the full payload: text, media, author, mentions, and ocr_text when OCR is enabled. The only field that can be incomplete is reply/quote context — a tweet caught by a fast push source can arrive with its in_reply_to reference or quoted_tweet body missing, in which case a twitter.post.update follows with those filled in. Store on event_id and merge the update if it arrives.

{
  "op": 0,
  "d": {
    "event": "twitter.post.new",
    "event_id": "evt_1234567890123456789",
    "task_info": {"handle": "elonmusk"},
    "data": {
      "id": "1234567890123456789",
      "created_at": 1712000000000,
      "type": "post",
      "text": "Hello world",
      "media": [{"type": "photo", "url": "https://pbs.twimg.com/media/..."}],
      "mentions": [{"screen_name": "vitalikbuterin"}],
      "author": {
        "id": "44196397",
        "handle": "elonmusk",
        "name": "Elon Musk",
        "avatar": "https://pbs.twimg.com/profile_images/...",
        "description": "CEO of Tesla, SpaceX, etc.",
        "verification": {"is_verified": true},
        "stats": {"followers": 190000000, "following": 800}
      },
      "in_reply_to": null,
      "quoted_tweet": null,
      "possibly_sensitive": false,
      "ocr_text": "GIGACHAD\nCA: 7xKXtg2CW87d97TXJSDpbD5jBkheTqA83TZRuJosgAsU",
      "extracted_cas": ["7xKXtg2CW87d97TXJSDpbD5jBkheTqA83TZRuJosgAsU"]
    }
  }
}

Tweet types in data.type: "post", "reply", "quote", "repost"

OCR & contract extraction (opt-in): For accounts with OCR enabled, tweets that contain images carry two extra fields inside data: ocr_text — the text read out of the tweet's image(s), or null if none — and extracted_cas — an array of Solana contract addresses parsed from that image text. This catches contract addresses posted as images to dodge text scanners, so you see the CA the moment it drops. Both fields are omitted entirely for accounts without OCR.

Event: twitter.post.update

A reply/quote context correction for a previously sent tweet — emitted only when the fast source detected a reply or quote without its full context. It re-delivers the same payload with type, in_reply_to, and quoted_tweet corrected; every other field (text, media, ocr_text) already arrived complete in twitter.post.new. Shares the same data.id and the same event_id (evt_<tweet_id>) as the original — dedupe on event_id and replace the stored data for this tweet.

{
  "op": 0,
  "d": {
    "event": "twitter.post.update",
    "event_id": "evt_1234567890123456789",
    "task_info": {"handle": "elonmusk"},
    "data": {
      "id": "1234567890123456789",
      "created_at": 1712000000000,
      "type": "quote",
      "text": "This is huge 👀",
      "media": [],
      "mentions": [],
      "author": {
        "id": "44196397",
        "handle": "elonmusk",
        "name": "Elon Musk",
        "avatar": "https://pbs.twimg.com/profile_images/...",
        "description": "CEO of Tesla, SpaceX, etc.",
        "verification": {"is_verified": true},
        "stats": {"followers": 190000000, "following": 800}
      },
      "in_reply_to": null,
      "quoted_tweet": {
        "id": "9876543210987654321",
        "text": "Original tweet text here",
        "author": {"handle": "vitalikbuterin", "name": "Vitalik Buterin"}
      },
      "possibly_sensitive": false
    }
  }
}

Event: twitter.tweet.deleted

{
  "op": 0,
  "d": {
    "event": "twitter.tweet.deleted",
    "event_id": "evt_del_elonmusk_1712000000",
    "task_info": {"handle": "elonmusk"},
    "data": {"tweet_id": "1234567890123456789"}
  }
}

data.tweet_id may be null if the specific tweet id could not be determined.

Event: twitter.following.new

{
  "op": 0,
  "d": {
    "event": "twitter.following.new",
    "event_id": "evt_f_elonmusk_1712000000",
    "task_info": {"handle": "elonmusk"},
    "data": {
      "id": "44196397",
      "handle": "vitalikbuterin",
      "name": "Vitalik Buterin"
    }
  }
}

Event: twitter.following.removed

Fires when a tracked account unfollows someone it previously followed. Same data shape as twitter.following.new — it identifies the account that was unfollowed. data.name/data.handle may be null if we no longer have that profile cached.

{
  "op": 0,
  "d": {
    "event": "twitter.following.removed",
    "event_id": "evt_fr_elonmusk_1712000000",
    "task_info": {"handle": "elonmusk"},
    "data": {
      "id": "44196397",
      "handle": "vitalikbuterin",
      "name": "Vitalik Buterin"
    }
  }
}

Testing follow / unfollow: add a Twitter account you control via POST /v1/dt/targets, connect the WebSocket, then from that account follow (or unfollow) any other user on Twitter. Within ~30–60 seconds you'll get a twitter.following.new (or twitter.following.removed) event on the stream. Detection is poll-based — Twitter exposes no real-time push for follow-graph changes — so it's seconds, not instant. Requires the follows module enabled on your account.

Event: twitter.profile.update

{
  "op": 0,
  "d": {
    "event": "twitter.profile.update",
    "event_id": "evt_p_elonmusk_1712000000",
    "task_info": {"handle": "elonmusk"},
    "data": {
      "field": "description",
      "prev": "Old bio text",
      "updated": "New bio text"
    }
  }
}

Fields: "description", "name", "avatar", "pinned_post"

Event: twitter.follower.new

{
  "op": 0,
  "d": {
    "event": "twitter.follower.new",
    "event_id": "evt_fl_elonmusk_1712000000",
    "task_info": {"handle": "elonmusk"},
    "data": {
      "id": "555555555",
      "handle": "newfollower",
      "name": "New Follower"
    }
  }
}

Example: JavaScript Client

const ws = new WebSocket('wss://api.xanguard.tech/v1/dt/realtime/ws');

ws.onmessage = (event) => {
  const msg = JSON.parse(event.data);
  switch (msg.op) {
    case 10: // HELLO
      ws.send(JSON.stringify({op: 2, d: 'dt_YOUR_API_KEY'}));
      break;
    case 4: // READY
      console.log('Connected:', msg.d.modules, msg.d.handles, 'handles');
      break;
    case 0: // EVENT
      console.log('Event:', msg.d.event, msg.d.data);
      break;
  }
};

// Heartbeat every 30s
setInterval(() => {
  if (ws.readyState === WebSocket.OPEN) {
    ws.send(JSON.stringify({op: 1}));
  }
}, 30000);

Example: Python Client

import asyncio, websockets, json

async def connect():
    async with websockets.connect('wss://api.xanguard.tech/v1/dt/realtime/ws') as ws:
        hello = json.loads(await ws.recv())  # HELLO
        await ws.send(json.dumps({"op": 2, "d": "dt_YOUR_API_KEY"}))
        ready = json.loads(await ws.recv())  # READY
        print(f"Connected: {ready['d']['modules']}, {ready['d']['handles']} handles")

        while True:
            msg = json.loads(await ws.recv())
            if msg["op"] == 0:  # EVENT
                print(f"{msg['d']['event']}: {msg['d']['data']}")

asyncio.run(connect())

Pricing

Priced by module tier and handle count — see the full table under Xanguard B2B → Pricing.


ECA (Early CA Alerts)

ECA detects pump.fun token launches that match community activity signals. Add a ticker, token name, contract address, or creator wallet to your watchlist, and ECA alerts you when a matching token appears on pump.fun. Entries expire after 4 hours. Free to use. Managed via the ECA section in @Xanguard_bot.

API

Auth: Bearer token with eca_ prefix.

Authorization: Bearer eca_your_api_key_here
MethodPathDescription
GET/v1/eca/watchlistList active watchlist entries
POST/v1/eca/watchlistAdd entry. Body: {"ticker": "DOGE", "token_name": "...", "contract_address": "...", "creator_address": "..."}
DELETE/v1/eca/watchlist/{id}Remove entry
GET/v1/eca/matchesRecent token matches (last 24h)
GET/v1/eca/webhookGet webhook URL
PUT/v1/eca/webhookSet webhook URL
GET/v1/eca/statusActive entries, total matches

WebSocket

wss://api.xanguard.tech/v1/eca/ws?api_key=eca_your_key

Receives real-time JSON events when a token launch matches your watchlist criteria.


Engagement Tracker

Engagement Tracker (ET) monitors real-time engagement changes on specific tweets — likes, retweets, replies, quotes, and bookmarks. Real-time engagement change detection with zero-delay alerts. Managed via @E_Xanguard_bot.

Bot Commands

CommandDescription
/startDashboard & subscription
/add <tweet_url>Add a tweet to monitor
/remove <tweet_id>Stop monitoring a tweet
/listList watched tweets
/apikeyView or regenerate API key
/helpCommand reference

Pricing

PlanTweetsPrice
ET 2525$100/mo
ET 5050$200/mo

API

Auth: Bearer token with et_ prefix.

Authorization: Bearer et_your_api_key_here
MethodPathDescription
GET/v1/et/targetsList watched tweets
POST/v1/et/targetsAdd tweets. Body: {"tweet_ids": ["123", "456"]}
DELETE/v1/et/targets/{tweet_id}Remove watched tweet
GET/v1/et/engagement/{tweet_id}Current engagement counts
GET/v1/et/webhookGet webhook URL
PUT/v1/et/webhookSet webhook URL
GET/v1/et/statusSubscription status

Engagement Response

{
  "ok": true,
  "data": {
    "tweet_id": "1234567890",
    "favorite_count": 42,
    "retweet_count": 10,
    "reply_count": 5,
    "quote_count": 2,
    "bookmark_count": 8,
    "last_updated": "2026-03-22T11:30:00Z"
  }
}

WebSocket

wss://api.xanguard.tech/v1/et/ws?api_key=et_your_key

Receives real-time JSON events when engagement counts change for any watched tweet.



PumpFun Livestream

PumpFun Livestream Tracker provides sub-second detection of pump.fun livestream starts and ends for monitored Solana wallets. Sub-second detection with zero cost per event. Managed via @PF_Xanguard_bot.

Bot Commands

CommandDescription
/startDashboard & subscription
/add <wallet>Add wallet to monitor
/remove <wallet>Remove wallet
/listList watched wallets
/apikeyView or regenerate API key
/helpCommand reference

Pricing

PlanWalletsPrice
Free1$0
PF 33$100/mo
PF 66$180/mo
PF 1010$270/mo
PF 2020$500/mo

API

Auth: Bearer token with pf_ prefix.

Authorization: Bearer pf_your_api_key_here
MethodPathDescription
GET/v1/pf/targetsList watched wallets
POST/v1/pf/targetsAdd wallet. Body: {"wallet_address": "DYw8j...", "label": "Dev1"}
DELETE/v1/pf/targets/{wallet}Remove wallet
GET/v1/pf/eventsRecent livestream events (max 50)
GET/v1/pf/webhookGet webhook URL
PUT/v1/pf/webhookSet webhook URL
GET/v1/pf/statusSubscription status

Event Response

{
  "ok": true,
  "data": [
    {
      "wallet_address": "DYw8j...",
      "mint": "9PR3c...",
      "token_name": "BONK",
      "token_symbol": "BONK",
      "event_type": "livestream_started",
      "detected_at": "2026-03-22T10:15:00Z",
      "delivery_latency_ms": 450
    }
  ]
}

WebSocket

wss://api.xanguard.tech/v1/pf/ws?api_key=pf_your_key

Receives real-time JSON events when watched wallets start or stop livestreaming on pump.fun.


Search Alerts

Search Alerts monitors Twitter/X for keyword matches in real time. Add up to 20 keyword queries and receive alerts when new matching tweets appear. Configurable intervals from 10 minutes to 6 hours. An add-on for @Xanguard_bot — managed via the Add-ons menu.

Pricing

PlanQueriesPrice
Search Alerts 2020$100/mo

API

Auth: Bearer token with sa_ prefix, generated via the API Key button in the Search Alerts management screen.

Authorization: Bearer sa_your_api_key_here
MethodPathDescription
GET/v1/sa/queriesList search queries
POST/v1/sa/queriesAdd query. Body: {"query_text": "solana airdrop"}
DELETE/v1/sa/queries/{id}Remove query
GET/v1/sa/webhookGet webhook URL
PUT/v1/sa/webhookSet webhook URL
GET/v1/sa/statusSubscription status, query count, max queries

Match Event

{
  "type": "search_alert",
  "data": {
    "query_id": 1,
    "query_text": "solana airdrop",
    "tweet_id": "1234567890",
    "full_text": "Massive Solana airdrop incoming...",
    "screen_name": "CryptoWhale",
    "display_name": "Crypto Whale"
  }
}

WebSocket

wss://api.xanguard.tech/v1/sa/ws?api_key=sa_your_key

Receives real-time JSON events when new tweets match your keyword queries.


Plans & Pricing

Choose a plan based on how many Twitter accounts you need to monitor and how many webhook endpoints you require. All paid plans include full access to the REST API, WebSocket streaming, and webhook delivery.

Free
$0

2 accounts

0 webhooks

Starter
$19/mo

10 accounts

1 webhook

Pro
$99/mo

75 accounts

5 webhooks

Business
$179/mo

150 accounts

10 webhooks

Enterprise
$349/mo

500 accounts

25 webhooks

Plan Price Accounts Webhooks
Free $0 2 0
Starter $19/mo 10 1
Growth $49/mo 35 2
Pro $99/mo 75 5
Business $179/mo 150 10
Enterprise $349/mo 500 25

Payment

All payments are made in SOL on the Solana blockchain. Prices are displayed in USD and converted to SOL at the current market rate at the time of payment. To subscribe or upgrade, use the Telegram bot — send /start and select your plan.

What Every Plan Includes

  • Real-time tweet detection (sub-second latency, typically 250-500ms)
  • Telegram bot notifications with forum topic support
  • REST API access (15 endpoints)
  • WebSocket streaming
  • Per-handle keyword filtering
  • Contract address auto-detection (Solana and Ethereum)
  • Notification filters (exclude replies, reposts, contracts only)
  • Mute/unmute individual accounts

Support

Need help getting set up or have questions about the API? Reach out through any of these channels.

Telegram Bot

Send /help to @Xanguard_bot for the built-in command reference, or use the bot directly to manage your account.

Direct Contact

For account issues, billing questions, or enterprise inquiries, message @notAdegen on Telegram.

Blog

Read the Xanguard Blog for guides, analysis, and product updates.

Main Site

Visit xanguard.tech for an overview of the platform, feature highlights, and FAQ.