Xanguard API Docs

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.

Xanguard APIs

All Xanguard APIs share one host — https://api.xanguard.tech — speak JSON, and wrap every response in the same envelope: {"ok":true,"data":…} on success, {"ok":false,"error":"…"} on failure. Each product lives under its own base path and issues keys with its own prefix:

API Base path Key prefix Issued by Purpose
Tweet Alerts (consumer) /v1 xg_ @Xanguard_bot /apikey Track accounts, settings, webhooks, WS alerts
B2B Monitoring /v1/dt dt_ @B2B_Xanguard_bot /apikey Handles, profile/follow data, realtime WS
CA Search /v1/search dt_ B2B add-on (Extra Features menu) Tweet search by CA/ticker/keyword
Community Watch /v1/cw cw_ @F_xanguard_bot Community events
Convergence Tracker /v1/ct ct_ @T_xanguard_bot Community convergence
ECA /v1/eca eca_ @Xanguard_bot pump.fun launch watchlist
Engagement Tracker /v1/et et_ @E_Xanguard_bot Per-tweet engagement
Trending Alerts /v1/trending trend_ @Trends_Xanguard_bot Trending feed
PumpFun Livestream /v1/pf pf_ @PF_Xanguard_bot Livestream start/stop
Search Alerts /v1/sa sa_ @Xanguard_bot Keyword search alerts

WebSocket auth

Consumer and product WebSockets authenticate with an ?api_key= query parameter (e.g. wss://api.xanguard.tech/v1/ws?api_key=xg_your_key). The B2B realtime WebSocket is the exception: it authenticates with a LOGIN opcode after connecting — see B2B Realtime WebSocket.

Keys are product-scoped. A dt_ key won't work on /v1/cw, a cw_ key won't work on /v1/et, and so on. Generate a key from the bot that owns the product you want to use.

Looking for bot setup and user guides instead? See the Telegram guides.


Conventions

Behavior shared by every Xanguard API, collected in one place.

Response Envelope

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

{
  "ok": true,
  "data": { ... }
}

{
  "ok": false,
  "error": "Invalid API key"
}

Authentication

All REST APIs authenticate with a Bearer token in the Authorization header:

Authorization: Bearer <prefix>_your_api_key_here

Each product issues keys with its own prefix (xg_, dt_, cw_, …) — see the API overview table for the full list and issuing bots. Keys are product-scoped. CA Search additionally accepts the twitterapi.io-compatible X-API-Key header.

Error Codes

Common HTTP status codes across the APIs:

StatusMeaning
400Bad request — missing or invalid field
401Authentication failed — missing, malformed, or invalid API key
403Not allowed — plan limit reached, feature not enabled on this key, or Free-tier key
404Resource not found (or no data collected yet)
409Conflict — resource already exists
429Rate limit or daily allowance exhausted — back off and retry
500Internal or upstream failure — retry
503Service temporarily unavailable — retry with backoff

B2B Monitoring and CA Search document per-endpoint error tables in their own sections: B2B API and CA Search.

Pagination

Two conventions exist. B2B list endpoints paginate with limit/offset query params (e.g. /v1/dt/followers/{handle}). CA Search uses an opaque cursor: pass the previous response's next_cursor as cursor to continue a truncated result set. Consumer API lists are unpaginated and return the full set.

Rate Limits

SurfaceLimit
Consumer REST (/v1)Per-key sliding window that scales with your tier; excess returns 429
B2B REST (/v1/dt)Not per-second rate-limited — 64 KB request-body cap; 5 concurrent WebSocket connections per key
CA Search (/v1/search)10 requests/sec per key + daily plan allowance
WebSockets (all)10 inbound messages/sec per connection

Webhooks

Webhook deliveries are signed POST requests with a JSON body. Every delivery includes an X-Signature header containing a lowercase HMAC-SHA256 hex digest of the raw request body, computed using your webhook secret (returned once at registration). 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)

Retries: if your endpoint returns a non-2xx status code or the request times out, Xanguard makes up to 3 delivery attempts with backoff (1s, then 2s between retries). After 10 consecutive failures across any deliveries, the webhook is automatically disabled — delete it and register a new one (new id + new secret) once your endpoint is healthy again.

Community Watch deliveries use the same signing scheme.


Quick Start

Consumer: Tweet Alerts

Track Twitter/X accounts and receive tweet alerts in your app — four steps:

  1. Open @Xanguard_bot, send /start, and choose a plan.
  2. Send /apikey to get your xg_ key. Base URL is https://api.xanguard.tech/v1.
  3. Add a handle: POST /v1/accounts with body {"handles":["elonmusk"]}.
  4. Receive alerts on the WebSocket (?api_key= auth) or via a signed webhook.

B2B: Handle Monitoring

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 guide.


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. Consumer API keys start with xg_ and are generated via /apikey in @Xanguard_bot. (B2B keys start with dt_ and come from @B2B_Xanguard_bot — they're separate products.) API access requires a paid plan — Free-tier keys get 403.

Authorization Header
Authorization: Bearer xg_your_api_key_here

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 per key using a sliding window; the limit scales with your subscription tier. Exceeding it returns 429 Too Many Requests — back off and retry.

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,
        "is_active": true,
        "exclude_replies": false,
        "exclude_reposts": false,
        "exclude_quotes": 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,
    "is_active": true,
    "exclude_replies": false,
    "exclude_reposts": false,
    "exclude_quotes": 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": true,
    "handle": "elonmusk"
  }
}
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.
exclude_quotes false Skip quote 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,
    "exclude_quotes": 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,
    "exclude_quotes": 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": "Starter",
        "display_name": "Starter",
        "price_usd": 19,
        "account_limit": 10,
        "max_webhooks": 1,
        "duration_hours": 720
      }
    ]
  }
}

The Free plan is not included in this list.

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
GET /v1/webhooks List active webhooks
DELETE /v1/webhooks/{id} Deactivate a webhook
POST /v1/webhooks

Register a new webhook endpoint (http or https — HTTPS recommended, since payloads travel signed but unencrypted). 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": 42,
    "url": "https://your-server.com/webhook",
    "events": ["tweet"],
    "filter_handles": [],
    "filter_keywords": [],
    "is_active": true,
    "consecutive_failures": 0,
    "created_at": "2026-07-21T12:00:00Z",
    "secret": "9f2c…(64 hex chars)…b81a"
  }
}

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": 42,
        "url": "https://your-server.com/webhook",
        "events": ["tweet"],
        "filter_handles": [],
        "filter_keywords": [],
        "is_active": true,
        "consecutive_failures": 0,
        "created_at": "2026-07-21T12:00:00Z"
      }
    ],
    "count": 1,
    "limit": 5
  }
}
DELETE /v1/webhooks/{id}

Deactivate a webhook. It will stop receiving deliveries immediately.

Response

JSON
{
  "ok": true,
  "data": {
    "deleted": true,
    "id": 42
  }
}

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-Signature header containing a lowercase HMAC-SHA256 hex digest of the raw request body, computed using your webhook secret. Always verify this signature before processing the payload.

Verification snippets in JavaScript and Python live under Conventions → Webhooks.

Retry Policy

If your endpoint returns a non-2xx status code or the request times out, Xanguard makes up to 3 delivery attempts with backoff (1s, then 2s between retries). After 10 consecutive failures across any deliveries, the webhook is automatically disabled — delete it and register a new one (new id + new secret) 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",
  "tweet_id": "1947000000000000000",
  "handle": "elonmusk",
  "text": "Just bought more $BTC",
  "url": "https://twitter.com/elonmusk/status/1947000000000000000",
  "image_url": null,
  "image_urls": [],
  "is_reply": false,
  "is_quote": false,
  "received_at": 1784646000120,
  "created_at": 1784645999800,
  "original_tweet_id": null,
  "possibly_sensitive": false,
  "mentions": []
}

received_at is when Xanguard detected the tweet; created_at is when Twitter says it was posted — the difference is your true detection latency. Quotes include an embedded quoted_tweet object (id, text, author); replies include in_reply_to_user / in_reply_to_tweet_id refs plus an embedded quoted_tweet carrying the hydrated parent tweet (id, text, author) — label by is_reply vs is_quote, not by quoted_tweet presence. Reply/quote context is hydrated inline before delivery (+60–90ms typical, 200ms cap, only on those events); plain tweets are unaffected. All timestamps are epoch milliseconds.

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": "Would exceed handle limit: 10 + 5 new = 15, max 10"
}

Limits

LimitValue
ConnectionsPer-plan concurrent connection cap — excess attempts are rejected with HTTP 429
Inbound messages10 messages/sec per connection — sustained bursts force a disconnect
App-level pingSend {"type":"ping"} to receive {"type":"pong"} (optional liveness check)

Keepalive

The server sends a WebSocket ping frame every 30 seconds. Most WebSocket libraries answer automatically. If pongs go missing for ~3 minutes (6 consecutive pings), 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())

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.

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", "display_name": "Elon Musk", "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 profile sync 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 for the handle (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",
        "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"],
        "hashtags": [],
        "urls": [],
        "cashtags": []
      }
    ],
    "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, or handle not in your target list"Handle limit reached (500/500)" · "@handle is not in your target list"
404Handle not found on Twitter, 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 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

Opcode-based protocol (HELLO → LOGIN → READY → EVENT stream, TweetCatcher-style). 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 closes the connection — reconnect and re-login.

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 (follows ~1-3s, unfollows ~3-6s typical)
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, "type": "blue"},
        "affiliation": null,
        "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"

Verification badges: author.verification.type is "blue" (individual), "business" (gold/org), "government" (grey/gov), or null (not verified) — don't treat is_verified alone as a blue check, it is true for all badge types. Affiliated accounts also carry author.affiliation{"label": "...", "icon_url": "..."} with the small organization/government logo shown next to the handle; null otherwise. Badge data comes from the profile cache and refreshes on the account's poll cycle. Embedded tweets (quoted_tweet, also the parent on replies) include the quoted author's avatar alongside handle/name.

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 contract addresses (Solana mints, pump.fun links, and EVM 0x addresses) parsed from that image text. For quote tweets, the quoted tweet's images are included (that's usually where the CA image lives); reposts are OCR'd on the original tweet's media. 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 context correction for a previously sent tweet — emitted only when the fast source detected a reply or quote without its full context, or (for OCR-enabled accounts) when a push-sourced event shipped without media that later hydration recovered. It re-delivers the same payload with type, in_reply_to, quoted_tweet corrected and, in the media-recovery case, media / ocr_text / extracted_cas filled in; every other field 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, "type": "blue"},
        "affiliation": null,
        "stats": {"followers": 190000000, "following": 800}
      },
      "in_reply_to": null,
      "quoted_tweet": {
        "id": "9876543210987654321",
        "text": "Original tweet text here",
        "author": {"handle": "vitalikbuterin", "name": "Vitalik Buterin", "avatar": "https://pbs.twimg.com/profile_images/..."}
      },
      "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",
      "bio": "Ethereum",
      "followers": 5200000,
      "following": 350,
      "protected": false
    }
  }
}

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",
      "bio": "Ethereum",
      "followers": 5200000,
      "following": 350,
      "protected": false
    }
  }
}

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.



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 an account to monitor. Body: {"handle": "elonmusk"}
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 or PUT /v1/cw/webhook. CW sends a signed POST request per event. Every community-change delivery uses the constant event name community_change — the specific type is inside data.event_type:

{
  "event": "community_change",
  "timestamp": 1784646000000,
  "data": {
    "event_type": "community_joined",
    "screen_name": "elonmusk",
    "twitter_user_id": "44196397",
    "community_id": "1493446837214187523",
    "community_name": "Crypto Builders",
    "description": "…",
    "member_count": 15420,
    "creator_screen_name": "someuser",
    "detected_at": 1784645998000,
    "detection_latency_ms": 1400
  }
}

data.event_type is one of: community_created, community_joined, community_renamed (adds old_name), community_description_changed (adds old_description), account_followed, new_follower. Timestamps are epoch milliseconds.

New-follower events arrive as a batch digest with their own envelope:

{
  "event": "new_followers",
  "timestamp": 1784646000000,
  "data": {
    "screen_name": "elonmusk",
    "twitter_user_id": "44196397",
    "followers": [
      {"user_id": "123", "screen_name": "newfan", "display_name": "New Fan", "followers_count": 320, "following_count": 150, "account_age_days": 400}
    ],
    "detected_at": 1784645998000
  }
}

Follow events (account_followed) use their own envelope:

{
  "event": "follow_change",
  "timestamp": 1784646000000,
  "data": {
    "screen_name": "elonmusk",
    "twitter_user_id": "44196397",
    "followed_user_id": "783214",
    "followed_screen_name": "someuser",
    "followed_display_name": "Some User",
    "followed_bio": "…",
    "followed_followers_count": 12000,
    "detected_at": 1784645998000
  }
}

Deliveries carry an X-Signature HMAC-SHA256 header (same verification scheme as the main API) and are retried with backoff on non-2xx responses.


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_hours, min_member_count)
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.


ECA API

Programmatic access to ECA (Early CA Alerts) — the pump.fun launch watchlist. For bot commands & pricing, see the ECA Telegram guide.

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 API

Programmatic access to Engagement Tracker — per-tweet engagement monitoring. For bot commands & pricing, see the Engagement Tracker Telegram guide.

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 API

Programmatic access to PumpFun Livestream — livestream start/stop detection for watched wallets. For bot commands & pricing, see the PumpFun Livestream Telegram guide.

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 API

Programmatic access to Search Alerts — keyword search alerts. For bot commands & pricing, see the Search Alerts Telegram guide.

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.


Changelog

2026-07-21

  • CA Search launched: POST /v1/search B2B add-on — tweet search by contract address, ticker, or keyword with 24h deep pagination. Plans from $100/mo. See CA Search.
  • Docs restructured into API docs and Telegram guides.

Support

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

Telegram Guides

Bot setup, commands, and user guides for every product live on the Telegram guides page.

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.