{
  "openapi": "3.0.3",
  "info": {
    "title": "Xanguard API",
    "description": "Real-time Twitter monitoring and alert platform. Sub-second tweet detection, community gate tracking, convergence detection, engagement monitoring, trending alerts, pump.fun livestream detection, keyword search alerts, and token launch alerts. Built for crypto traders, DeFi protocols, trading bots, and AI agents.",
    "version": "1.1.1",
    "contact": {
      "name": "Xanguard Support",
      "url": "https://t.me/Xanguard_bot"
    },
    "x-logo": {
      "url": "https://xanguard.tech/favicon.svg"
    }
  },
  "servers": [
    {
      "url": "https://api.xanguard.tech",
      "description": "Production"
    }
  ],
  "tags": [
    {
      "name": "System",
      "description": "Health and status"
    },
    {
      "name": "Accounts",
      "description": "Manage tracked Twitter accounts"
    },
    {
      "name": "Settings",
      "description": "User settings and subscription"
    },
    {
      "name": "Webhooks",
      "description": "Webhook callback management"
    },
    {
      "name": "Feed",
      "description": "Tweet feed and streaming"
    },
    {
      "name": "Community Watch",
      "description": "Twitter community gate monitoring"
    },
    {
      "name": "Convergence Tracker",
      "description": "Multi-account community convergence detection"
    },
    {
      "name": "Xanguard B2B",
      "description": "Real-time Twitter/X monitoring API (tweets, follows, profile changes, followers)"
    },
    {
      "name": "ECA",
      "description": "Early CA alerts \u2014 token launch matching from community signals"
    },
    {
      "name": "Engagement Tracker",
      "description": "Real-time tweet engagement monitoring via SSE"
    },
    {
      "name": "Trending Alerts",
      "description": "Twitter trending topic notifications across 24 categories"
    },
    {
      "name": "PumpFun Livestream",
      "description": "Sub-second pump.fun livestream detection via NATS"
    },
    {
      "name": "Search Alerts",
      "description": "Twitter-wide keyword search monitoring"
    }
  ],
  "paths": {
    "/health": {
      "get": {
        "tags": [
          "System"
        ],
        "summary": "Health check",
        "description": "Returns system health status including database connectivity, listener status, and WebSocket connections.",
        "operationId": "getHealth",
        "responses": {
          "200": {
            "description": "System healthy",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "status": {
                      "type": "string",
                      "example": "ok"
                    },
                    "db": {
                      "type": "string",
                      "example": "ok"
                    },
                    "listeners": {
                      "type": "integer",
                      "example": 3
                    },
                    "ws_connections": {
                      "type": "integer",
                      "example": 5
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/ws": {
      "get": {
        "tags": [
          "Feed"
        ],
        "summary": "WebSocket streaming",
        "description": "Real-time tweet streaming via WebSocket. Connect with your API key as a query parameter. Receives JSON messages for each detected tweet in real-time.",
        "operationId": "wsStream",
        "parameters": [
          {
            "name": "key",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Your API key"
          }
        ],
        "responses": {
          "101": {
            "description": "WebSocket upgrade successful"
          },
          "403": {
            "description": "Invalid API key or free tier"
          }
        }
      }
    },
    "/v1/accounts": {
      "get": {
        "tags": [
          "Accounts"
        ],
        "summary": "List tracked accounts",
        "description": "Returns all Twitter accounts being monitored for the authenticated user.",
        "operationId": "listAccounts",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "List of tracked accounts",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AccountListResponse"
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": [
          "Accounts"
        ],
        "summary": "Add tracked accounts",
        "description": "Add up to 25 Twitter handles per request to monitor. Handles are resolved and assigned to listener accounts automatically.",
        "operationId": "addAccounts",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "handles"
                ],
                "properties": {
                  "handles": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "maxItems": 25,
                    "example": [
                      "elonmusk",
                      "VitalikButerin"
                    ]
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Accounts added successfully",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiResponse"
                }
              }
            }
          },
          "400": {
            "description": "Invalid handles or limit exceeded"
          },
          "403": {
            "description": "Account limit reached for subscription tier"
          }
        }
      }
    },
    "/v1/accounts/{handle}": {
      "get": {
        "tags": [
          "Accounts"
        ],
        "summary": "Get account details",
        "description": "Returns details for a specific tracked Twitter account including keywords, mute status, and listener assignment.",
        "operationId": "getAccount",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "handle",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Twitter handle (without @)"
          }
        ],
        "responses": {
          "200": {
            "description": "Account details",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AccountResponse"
                }
              }
            }
          },
          "404": {
            "description": "Account not tracked"
          }
        }
      },
      "delete": {
        "tags": [
          "Accounts"
        ],
        "summary": "Remove tracked account",
        "description": "Stop monitoring a Twitter account.",
        "operationId": "removeAccount",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "handle",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Account removed"
          },
          "404": {
            "description": "Account not tracked"
          }
        }
      }
    },
    "/v1/accounts/{handle}/keywords": {
      "put": {
        "tags": [
          "Accounts"
        ],
        "summary": "Set keyword filter",
        "description": "Set include/exclude keyword filters for a tracked account. Tweets are only delivered if they match include keywords (if set) and don't match exclude keywords.",
        "operationId": "setKeywords",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "handle",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "include": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "description": "Only deliver tweets containing these words"
                  },
                  "exclude": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "description": "Suppress tweets containing these words"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Keywords updated"
          }
        }
      },
      "delete": {
        "tags": [
          "Accounts"
        ],
        "summary": "Clear keyword filter",
        "description": "Remove all keyword filters for a tracked account. All tweets will be delivered.",
        "operationId": "clearKeywords",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "handle",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Keywords cleared"
          }
        }
      }
    },
    "/v1/accounts/{handle}/mute": {
      "put": {
        "tags": [
          "Accounts"
        ],
        "summary": "Mute/unmute account",
        "description": "Toggle mute status for a tracked account. Muted accounts are still monitored but notifications are suppressed.",
        "operationId": "muteAccount",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "handle",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "muted"
                ],
                "properties": {
                  "muted": {
                    "type": "boolean"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Mute status updated"
          }
        }
      }
    },
    "/v1/settings": {
      "get": {
        "tags": [
          "Settings"
        ],
        "summary": "Get user settings",
        "description": "Returns current user settings including notification preferences and filter configuration.",
        "operationId": "getSettings",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "User settings",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiResponse"
                }
              }
            }
          }
        }
      },
      "patch": {
        "tags": [
          "Settings"
        ],
        "summary": "Update user settings",
        "description": "Update notification preferences including reply/quote filtering.",
        "operationId": "updateSettings",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "suppress_replies": {
                    "type": "boolean",
                    "description": "Hide reply tweets"
                  },
                  "suppress_quotes": {
                    "type": "boolean",
                    "description": "Hide quote tweets"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Settings updated"
          }
        }
      }
    },
    "/v1/subscription": {
      "get": {
        "tags": [
          "Settings"
        ],
        "summary": "Get subscription info",
        "description": "Returns the user's active subscription tier, limits, usage, and expiration date.",
        "operationId": "getSubscription",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Subscription details",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiResponse"
                }
              }
            }
          }
        }
      }
    },
    "/v1/plans": {
      "get": {
        "tags": [
          "Settings"
        ],
        "summary": "List subscription plans",
        "description": "Returns all available subscription tiers with pricing and limits.",
        "operationId": "listPlans",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Available plans",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiResponse"
                }
              }
            }
          }
        }
      }
    },
    "/v1/webhooks": {
      "get": {
        "tags": [
          "Webhooks"
        ],
        "summary": "List webhooks",
        "description": "Returns all registered webhook URLs for the authenticated user. Secret field is omitted from response.",
        "operationId": "listWebhooks",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "List of webhooks",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiResponse"
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": [
          "Webhooks"
        ],
        "summary": "Register webhook",
        "description": "Register a callback URL to receive tweet notifications via HTTPS POST. Payloads are signed with HMAC-SHA256. Failed deliveries are retried with exponential backoff (3 attempts).",
        "operationId": "createWebhook",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "url"
                ],
                "properties": {
                  "url": {
                    "type": "string",
                    "format": "uri",
                    "description": "HTTPS callback URL",
                    "example": "https://your-server.com/webhooks/twitter"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Webhook registered. Response includes the HMAC secret for signature verification.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookCreatedResponse"
                }
              }
            }
          },
          "403": {
            "description": "Webhook limit reached for subscription tier"
          }
        }
      }
    },
    "/v1/webhooks/{id}": {
      "delete": {
        "tags": [
          "Webhooks"
        ],
        "summary": "Remove webhook",
        "description": "Soft-deactivate a registered webhook.",
        "operationId": "deleteWebhook",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Webhook deactivated"
          },
          "404": {
            "description": "Webhook not found"
          }
        }
      }
    },
    "/v1/feed": {
      "get": {
        "tags": [
          "Feed"
        ],
        "summary": "Get tweet feed",
        "description": "Returns recent tweets from all tracked accounts. Requires web dashboard authentication (JWT cookie).",
        "operationId": "getFeed",
        "security": [
          {
            "cookieAuth": []
          }
        ],
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "default": 50
            },
            "description": "Max tweets to return"
          },
          {
            "name": "before",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date-time"
            },
            "description": "Cursor for pagination"
          }
        ],
        "responses": {
          "200": {
            "description": "Tweet feed",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiResponse"
                }
              }
            }
          }
        }
      }
    },
    "/v1/cw/targets": {
      "get": {
        "tags": [
          "Community Watch"
        ],
        "summary": "List watched handles",
        "description": "Returns all Twitter handles being monitored for community gate activity.",
        "operationId": "cwListTargets",
        "security": [
          {
            "cwAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "List of watched handles",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiResponse"
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": [
          "Community Watch"
        ],
        "summary": "Add watched handle",
        "description": "Start monitoring a Twitter handle for community gate changes (join, create, rename, description change).",
        "operationId": "cwAddTarget",
        "security": [
          {
            "cwAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "handle"
                ],
                "properties": {
                  "handle": {
                    "type": "string",
                    "example": "CryptoDevX"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Handle added to watch list"
          },
          "403": {
            "description": "Target limit reached for subscription"
          }
        }
      }
    },
    "/v1/cw/targets/{handle}": {
      "delete": {
        "tags": [
          "Community Watch"
        ],
        "summary": "Remove watched handle",
        "description": "Stop monitoring a Twitter handle for community gate activity.",
        "operationId": "cwRemoveTarget",
        "security": [
          {
            "cwAuth": []
          }
        ],
        "parameters": [
          {
            "name": "handle",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Handle removed"
          },
          "404": {
            "description": "Handle not watched"
          }
        }
      }
    },
    "/v1/cw/webhook": {
      "get": {
        "tags": [
          "Community Watch"
        ],
        "summary": "Get CW webhook",
        "description": "Returns the currently configured webhook URL for Community Watch events.",
        "operationId": "cwGetWebhook",
        "security": [
          {
            "cwAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Webhook configuration"
          }
        }
      },
      "put": {
        "tags": [
          "Community Watch"
        ],
        "summary": "Set CW webhook",
        "description": "Configure a webhook URL to receive Community Watch events (community_joined, community_created, community_renamed, description_changed, followed, new_follower_digest).",
        "operationId": "cwSetWebhook",
        "security": [
          {
            "cwAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "url"
                ],
                "properties": {
                  "url": {
                    "type": "string",
                    "format": "uri",
                    "example": "https://your-server.com/webhooks/cw"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Webhook set"
          }
        }
      }
    },
    "/v1/cw/settings": {
      "get": {
        "tags": [
          "Community Watch"
        ],
        "summary": "Get CW settings",
        "description": "Returns Community Watch client settings including event type subscriptions.",
        "operationId": "cwGetSettings",
        "security": [
          {
            "cwAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "CW settings"
          }
        }
      },
      "patch": {
        "tags": [
          "Community Watch"
        ],
        "summary": "Update CW settings",
        "description": "Update which event types to receive notifications for.",
        "operationId": "cwUpdateSettings",
        "security": [
          {
            "cwAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "event_types": {
                    "type": "array",
                    "items": {
                      "type": "string",
                      "enum": [
                        "community_joined",
                        "community_created",
                        "community_renamed",
                        "description_changed",
                        "followed",
                        "new_follower_digest"
                      ]
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Settings updated"
          }
        }
      }
    },
    "/v1/cw/status": {
      "get": {
        "tags": [
          "Community Watch"
        ],
        "summary": "Get CW status",
        "description": "Returns Community Watch subscription status and health.",
        "operationId": "cwGetStatus",
        "security": [
          {
            "cwAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "CW status"
          }
        }
      }
    },
    "/v1/cw/ws": {
      "get": {
        "tags": [
          "Community Watch"
        ],
        "summary": "CW WebSocket streaming",
        "description": "Real-time Community Watch events via WebSocket. Receives JSON messages for community gate changes as they are detected.",
        "operationId": "cwWsStream",
        "parameters": [
          {
            "name": "api_key",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Your CW API key (cw_ prefix)"
          }
        ],
        "responses": {
          "101": {
            "description": "WebSocket upgrade successful"
          },
          "403": {
            "description": "Invalid API key"
          }
        }
      }
    },
    "/v1/ct/targets": {
      "get": {
        "tags": [
          "Convergence Tracker"
        ],
        "summary": "List CT targets",
        "description": "Returns all Twitter handles being tracked for community convergence detection.",
        "operationId": "ctListTargets",
        "security": [
          {
            "ctAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "List of tracked handles"
          }
        }
      },
      "post": {
        "tags": [
          "Convergence Tracker"
        ],
        "summary": "Add CT target",
        "description": "Add a Twitter handle for convergence tracking. The system monitors which communities this account joins and checks for overlap with other tracked accounts.",
        "operationId": "ctAddTarget",
        "security": [
          {
            "ctAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "handle"
                ],
                "properties": {
                  "handle": {
                    "type": "string",
                    "example": "CryptoDevX"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Target added"
          },
          "403": {
            "description": "Target limit reached"
          }
        }
      }
    },
    "/v1/ct/targets/{handle}": {
      "delete": {
        "tags": [
          "Convergence Tracker"
        ],
        "summary": "Remove CT target",
        "operationId": "ctRemoveTarget",
        "security": [
          {
            "ctAuth": []
          }
        ],
        "parameters": [
          {
            "name": "handle",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Target removed"
          }
        }
      }
    },
    "/v1/ct/convergence": {
      "get": {
        "tags": [
          "Convergence Tracker"
        ],
        "summary": "Get convergence results",
        "description": "Returns current convergence detections -- groups of tracked accounts that appear in the same Twitter community within the configured time window.",
        "operationId": "ctGetConvergence",
        "security": [
          {
            "ctAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Convergence results",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiResponse"
                }
              }
            }
          }
        }
      }
    },
    "/v1/ct/convergence/history": {
      "get": {
        "tags": [
          "Convergence Tracker"
        ],
        "summary": "Get convergence history",
        "description": "Returns historical convergence events.",
        "operationId": "ctGetConvergenceHistory",
        "security": [
          {
            "ctAuth": []
          }
        ],
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "default": 50
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Convergence history"
          }
        }
      }
    },
    "/v1/ct/settings": {
      "get": {
        "tags": [
          "Convergence Tracker"
        ],
        "summary": "Get CT settings",
        "operationId": "ctGetSettings",
        "security": [
          {
            "ctAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "CT settings"
          }
        }
      },
      "patch": {
        "tags": [
          "Convergence Tracker"
        ],
        "summary": "Update CT settings",
        "description": "Update convergence detection parameters.",
        "operationId": "ctUpdateSettings",
        "security": [
          {
            "ctAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "min_convergence": {
                    "type": "integer",
                    "minimum": 2,
                    "maximum": 100,
                    "description": "Minimum tracked accounts in same community to trigger alert"
                  },
                  "time_window_hours": {
                    "type": "integer",
                    "minimum": 6,
                    "maximum": 48,
                    "description": "How recent the community membership must be"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Settings updated"
          }
        }
      }
    },
    "/v1/ct/webhook": {
      "get": {
        "tags": [
          "Convergence Tracker"
        ],
        "summary": "Get CT webhook",
        "operationId": "ctGetWebhook",
        "security": [
          {
            "ctAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Webhook configuration"
          }
        }
      },
      "put": {
        "tags": [
          "Convergence Tracker"
        ],
        "summary": "Set CT webhook",
        "operationId": "ctSetWebhook",
        "security": [
          {
            "ctAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "url"
                ],
                "properties": {
                  "url": {
                    "type": "string",
                    "format": "uri"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Webhook set"
          }
        }
      }
    },
    "/v1/ct/status": {
      "get": {
        "tags": [
          "Convergence Tracker"
        ],
        "summary": "Get CT status",
        "operationId": "ctGetStatus",
        "security": [
          {
            "ctAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "CT status"
          }
        }
      }
    },
    "/v1/ct/ws": {
      "get": {
        "tags": [
          "Convergence Tracker"
        ],
        "summary": "CT WebSocket streaming",
        "description": "Real-time convergence detection events via WebSocket.",
        "operationId": "ctWsStream",
        "parameters": [
          {
            "name": "api_key",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Your CT API key (ct_ prefix)"
          }
        ],
        "responses": {
          "101": {
            "description": "WebSocket upgrade successful"
          },
          "403": {
            "description": "Invalid API key"
          }
        }
      }
    },
    "/v1/dt/targets": {
      "get": {
        "tags": [
          "Xanguard B2B"
        ],
        "summary": "List DT targets",
        "description": "Returns all Twitter handles monitored for the authenticated client.",
        "operationId": "dtListTargets",
        "security": [
          {
            "dtAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "List of monitored handles"
          }
        }
      },
      "post": {
        "tags": [
          "Xanguard B2B"
        ],
        "summary": "Add DT target",
        "description": "Add a Twitter handle to monitor (profile, tweets, following, followers, communities, likes, media).",
        "operationId": "dtAddTarget",
        "security": [
          {
            "dtAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "handle"
                ],
                "properties": {
                  "handle": {
                    "type": "string",
                    "example": "CryptoDevX"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Target added"
          },
          "403": {
            "description": "Target limit reached"
          }
        }
      }
    },
    "/v1/dt/targets/{handle}": {
      "delete": {
        "tags": [
          "Xanguard B2B"
        ],
        "summary": "Remove DT target",
        "operationId": "dtRemoveTarget",
        "security": [
          {
            "dtAuth": []
          }
        ],
        "parameters": [
          {
            "name": "handle",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Target removed"
          }
        }
      }
    },
    "/v1/dt/profile/{handle}": {
      "get": {
        "tags": [
          "Xanguard B2B"
        ],
        "summary": "Get profile snapshot",
        "description": "Returns the latest profile data for a Twitter handle including bio, follower count, following count, and verified status.",
        "operationId": "dtGetProfile",
        "security": [
          {
            "dtAuth": []
          }
        ],
        "parameters": [
          {
            "name": "handle",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Profile snapshot"
          },
          "403": {
            "description": "Handle not in your watch list"
          },
          "404": {
            "description": "No data collected yet"
          }
        }
      }
    },
    "/v1/dt/profile/{handle}/history": {
      "get": {
        "tags": [
          "Xanguard B2B"
        ],
        "summary": "Get profile history",
        "description": "Returns historical profile snapshots showing how follower count, following count, and bio have changed over time.",
        "operationId": "dtGetProfileHistory",
        "security": [
          {
            "dtAuth": []
          }
        ],
        "parameters": [
          {
            "name": "handle",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Profile history"
          }
        }
      }
    },
    "/v1/dt/tweets/{handle}": {
      "get": {
        "tags": [
          "Xanguard B2B"
        ],
        "summary": "Get tweets",
        "description": "Returns recent tweets from a tracked handle. Updated continuously. Includes full text, media URLs, cashtags, and engagement metrics.",
        "operationId": "dtGetTweets",
        "security": [
          {
            "dtAuth": []
          }
        ],
        "parameters": [
          {
            "name": "handle",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "default": 50
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Tweet list"
          }
        }
      }
    },
    "/v1/dt/following/{handle}": {
      "get": {
        "tags": [
          "Xanguard B2B"
        ],
        "summary": "Get following list",
        "description": "Returns the list of accounts a tracked handle follows. Refreshed on a rolling basis.",
        "operationId": "dtGetFollowing",
        "security": [
          {
            "dtAuth": []
          }
        ],
        "parameters": [
          {
            "name": "handle",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Following list"
          }
        }
      }
    },
    "/v1/dt/followers/{handle}": {
      "get": {
        "tags": [
          "Xanguard B2B"
        ],
        "summary": "Get followers list",
        "description": "Returns the list of accounts following a tracked handle. Refreshed on a rolling basis.",
        "operationId": "dtGetFollowers",
        "security": [
          {
            "dtAuth": []
          }
        ],
        "parameters": [
          {
            "name": "handle",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Followers list"
          }
        }
      }
    },
    "/v1/dt/communities/{handle}": {
      "get": {
        "tags": [
          "Xanguard B2B"
        ],
        "summary": "Get communities",
        "description": "Returns the Twitter communities a tracked handle has joined. Refreshed on a rolling basis.",
        "operationId": "dtGetCommunities",
        "security": [
          {
            "dtAuth": []
          }
        ],
        "parameters": [
          {
            "name": "handle",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Communities list"
          }
        }
      }
    },
    "/v1/dt/social/diff/{handle}": {
      "get": {
        "tags": [
          "Xanguard B2B"
        ],
        "summary": "Get social diff",
        "description": "Returns changes in social metrics (new/lost followers, new/lost following) over time.",
        "operationId": "dtGetSocialDiff",
        "security": [
          {
            "dtAuth": []
          }
        ],
        "parameters": [
          {
            "name": "handle",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Social diff"
          }
        }
      }
    },
    "/v1/dt/webhook": {
      "get": {
        "tags": [
          "Xanguard B2B"
        ],
        "summary": "Get DT webhook",
        "operationId": "dtGetWebhook",
        "security": [
          {
            "dtAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Webhook configuration"
          }
        }
      },
      "put": {
        "tags": [
          "Xanguard B2B"
        ],
        "summary": "Set DT webhook",
        "operationId": "dtSetWebhook",
        "security": [
          {
            "dtAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "url"
                ],
                "properties": {
                  "url": {
                    "type": "string",
                    "format": "uri"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Webhook set"
          }
        }
      }
    },
    "/v1/dt/status": {
      "get": {
        "tags": [
          "Xanguard B2B"
        ],
        "summary": "Get DT status",
        "description": "Returns Xanguard B2B service status and quota usage.",
        "operationId": "dtGetStatus",
        "security": [
          {
            "dtAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "DT status"
          }
        }
      }
    },
    "/v1/dt/ws": {
      "get": {
        "tags": [
          "Xanguard B2B"
        ],
        "summary": "DT WebSocket streaming",
        "description": "Real-time tweet stream via WebSocket. Receives new tweets for your monitored handles as {\"event_type\":\"tweet\",...} frames after a {\"event_type\":\"connected\"} greeting. No handshake or heartbeat required.",
        "operationId": "dtWsStream",
        "parameters": [
          {
            "name": "api_key",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Your DT API key (dt_ prefix)"
          }
        ],
        "responses": {
          "101": {
            "description": "WebSocket upgrade successful"
          },
          "403": {
            "description": "Invalid API key"
          }
        }
      }
    },
    "/v1/eca/watchlist": {
      "get": {
        "tags": [
          "ECA"
        ],
        "summary": "List watchlist entries",
        "description": "Returns all active ECA watchlist entries (not expired, not yet matched).",
        "operationId": "ecaListWatchlist",
        "security": [
          {
            "ecaAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Active watchlist entries",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/EcaWatchlistEntry"
                      }
                    }
                  }
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": [
          "ECA"
        ],
        "summary": "Add watchlist entry",
        "description": "Add a token to the ECA watchlist. Entries expire after 4 hours. Maximum 1 active entry at a time. Provide at least one of: ticker, token_name, contract_address, or creator_address.",
        "operationId": "ecaAddWatchlist",
        "security": [
          {
            "ecaAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "ticker": {
                    "type": "string",
                    "example": "DOGE"
                  },
                  "token_name": {
                    "type": "string",
                    "example": "Dogecoin"
                  },
                  "contract_address": {
                    "type": "string",
                    "description": "Solana mint address"
                  },
                  "creator_address": {
                    "type": "string",
                    "description": "Token creator wallet"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Entry added"
          },
          "400": {
            "description": "No fields provided or limit reached"
          }
        }
      }
    },
    "/v1/eca/watchlist/{id}": {
      "delete": {
        "tags": [
          "ECA"
        ],
        "summary": "Remove watchlist entry",
        "operationId": "ecaRemoveWatchlist",
        "security": [
          {
            "ecaAuth": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Entry removed"
          },
          "404": {
            "description": "Entry not found"
          }
        }
      }
    },
    "/v1/eca/matches": {
      "get": {
        "tags": [
          "ECA"
        ],
        "summary": "Get recent matches",
        "description": "Returns token launch matches from the last 24 hours, including mint address, match type, and detection time.",
        "operationId": "ecaGetMatches",
        "security": [
          {
            "ecaAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Recent matches",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/EcaMatch"
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/eca/webhook": {
      "get": {
        "tags": [
          "ECA"
        ],
        "summary": "Get ECA webhook",
        "operationId": "ecaGetWebhook",
        "security": [
          {
            "ecaAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Webhook configuration"
          }
        }
      },
      "put": {
        "tags": [
          "ECA"
        ],
        "summary": "Set ECA webhook",
        "description": "Configure a webhook URL to receive ECA match notifications. Returns a signing secret for HMAC-SHA256 verification.",
        "operationId": "ecaSetWebhook",
        "security": [
          {
            "ecaAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "url"
                ],
                "properties": {
                  "url": {
                    "type": "string",
                    "format": "uri"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Webhook set with signing secret"
          }
        }
      }
    },
    "/v1/eca/status": {
      "get": {
        "tags": [
          "ECA"
        ],
        "summary": "Get ECA status",
        "description": "Returns ECA subscription status including active entry count, total matches, and max entries allowed.",
        "operationId": "ecaGetStatus",
        "security": [
          {
            "ecaAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "ECA status",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "active_entries": {
                          "type": "integer"
                        },
                        "total_matches": {
                          "type": "integer"
                        },
                        "max_entries": {
                          "type": "integer"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/eca/ws": {
      "get": {
        "tags": [
          "ECA"
        ],
        "summary": "ECA WebSocket streaming",
        "description": "Real-time ECA match events via WebSocket. Receives JSON messages when a token launch matches your watchlist criteria.",
        "operationId": "ecaWsStream",
        "parameters": [
          {
            "name": "api_key",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Your ECA API key (eca_ prefix)"
          }
        ],
        "responses": {
          "101": {
            "description": "WebSocket upgrade successful"
          },
          "403": {
            "description": "Invalid API key"
          }
        }
      }
    },
    "/v1/et/targets": {
      "get": {
        "tags": [
          "Engagement Tracker"
        ],
        "summary": "List watched tweets",
        "description": "Returns all tweet IDs being monitored for engagement changes.",
        "operationId": "etListTargets",
        "security": [
          {
            "etAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "List of watched tweets",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/EtWatchedTweet"
                      }
                    }
                  }
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": [
          "Engagement Tracker"
        ],
        "summary": "Add tweets to watch",
        "description": "Add tweet IDs to monitor for engagement changes (likes, retweets, replies, quotes, bookmarks). Changes are delivered in real-time via SSE.",
        "operationId": "etAddTargets",
        "security": [
          {
            "etAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "tweet_ids"
                ],
                "properties": {
                  "tweet_ids": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "example": [
                      "1234567890",
                      "9876543210"
                    ]
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Tweets added to watchlist"
          },
          "403": {
            "description": "Tweet limit reached for subscription"
          }
        }
      }
    },
    "/v1/et/targets/{tweet_id}": {
      "delete": {
        "tags": [
          "Engagement Tracker"
        ],
        "summary": "Remove watched tweet",
        "operationId": "etRemoveTarget",
        "security": [
          {
            "etAuth": []
          }
        ],
        "parameters": [
          {
            "name": "tweet_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Tweet removed from watchlist"
          }
        }
      }
    },
    "/v1/et/engagement/{tweet_id}": {
      "get": {
        "tags": [
          "Engagement Tracker"
        ],
        "summary": "Get tweet engagement",
        "description": "Returns current engagement counts for a watched tweet (likes, retweets, replies, quotes, bookmarks).",
        "operationId": "etGetEngagement",
        "security": [
          {
            "etAuth": []
          }
        ],
        "parameters": [
          {
            "name": "tweet_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Engagement counts",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    },
                    "data": {
                      "$ref": "#/components/schemas/EtEngagement"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Tweet not in your watchlist"
          },
          "404": {
            "description": "No engagement data yet"
          }
        }
      }
    },
    "/v1/et/webhook": {
      "get": {
        "tags": [
          "Engagement Tracker"
        ],
        "summary": "Get ET webhook",
        "operationId": "etGetWebhook",
        "security": [
          {
            "etAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Webhook configuration"
          }
        }
      },
      "put": {
        "tags": [
          "Engagement Tracker"
        ],
        "summary": "Set ET webhook",
        "description": "Configure a webhook URL to receive engagement change notifications.",
        "operationId": "etSetWebhook",
        "security": [
          {
            "etAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "url"
                ],
                "properties": {
                  "url": {
                    "type": "string",
                    "format": "uri"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Webhook set with signing secret"
          }
        }
      }
    },
    "/v1/et/status": {
      "get": {
        "tags": [
          "Engagement Tracker"
        ],
        "summary": "Get ET status",
        "description": "Returns subscription status including tweets watched, max tweet limit, and subscription expiry.",
        "operationId": "etGetStatus",
        "security": [
          {
            "etAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "ET status",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "is_subscribed": {
                          "type": "boolean"
                        },
                        "tweets_watched": {
                          "type": "integer"
                        },
                        "max_tweets": {
                          "type": "integer"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/et/ws": {
      "get": {
        "tags": [
          "Engagement Tracker"
        ],
        "summary": "ET WebSocket streaming",
        "description": "Real-time engagement change events via WebSocket. Receives JSON messages when engagement counts change for any watched tweet.",
        "operationId": "etWsStream",
        "parameters": [
          {
            "name": "api_key",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Your ET API key (et_ prefix)"
          }
        ],
        "responses": {
          "101": {
            "description": "WebSocket upgrade successful"
          },
          "403": {
            "description": "Invalid API key"
          }
        }
      }
    },
    "/v1/trending/categories": {
      "get": {
        "tags": [
          "Trending Alerts"
        ],
        "summary": "List all categories",
        "description": "Returns all 24 available trending categories with subscription status for each.",
        "operationId": "trendingListCategories",
        "security": [
          {
            "trendingAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Category list",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/TrendingCategory"
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/trending/subscriptions": {
      "get": {
        "tags": [
          "Trending Alerts"
        ],
        "summary": "Get subscribed categories",
        "description": "Returns the categories the client is currently subscribed to, along with max category limit.",
        "operationId": "trendingGetSubscriptions",
        "security": [
          {
            "trendingAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Subscribed categories",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "categories": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          }
                        },
                        "max_categories": {
                          "type": "integer"
                        },
                        "is_subscribed": {
                          "type": "boolean"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        }
      },
      "put": {
        "tags": [
          "Trending Alerts"
        ],
        "summary": "Update subscribed categories",
        "description": "Replace the list of subscribed trending categories. Free tier: 1 non-crypto category. Pro tier: all 24 categories.",
        "operationId": "trendingUpdateSubscriptions",
        "security": [
          {
            "trendingAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "categories"
                ],
                "properties": {
                  "categories": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "example": [
                      "crypto",
                      "tech",
                      "gaming"
                    ]
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Subscriptions updated"
          },
          "400": {
            "description": "Invalid category slug or limit exceeded"
          }
        }
      }
    },
    "/v1/trending/webhook": {
      "get": {
        "tags": [
          "Trending Alerts"
        ],
        "summary": "Get Trending webhook",
        "operationId": "trendingGetWebhook",
        "security": [
          {
            "trendingAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Webhook configuration"
          }
        }
      },
      "put": {
        "tags": [
          "Trending Alerts"
        ],
        "summary": "Set Trending webhook",
        "description": "Configure a webhook URL to receive trending topic notifications.",
        "operationId": "trendingSetWebhook",
        "security": [
          {
            "trendingAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "url"
                ],
                "properties": {
                  "url": {
                    "type": "string",
                    "format": "uri"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Webhook set with signing secret"
          }
        }
      }
    },
    "/v1/trending/status": {
      "get": {
        "tags": [
          "Trending Alerts"
        ],
        "summary": "Get Trending status",
        "description": "Returns subscription status including subscribed category count and max limit.",
        "operationId": "trendingGetStatus",
        "security": [
          {
            "trendingAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Trending status",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "is_subscribed": {
                          "type": "boolean"
                        },
                        "categories_count": {
                          "type": "integer"
                        },
                        "max_categories": {
                          "type": "integer"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/trending/ws": {
      "get": {
        "tags": [
          "Trending Alerts"
        ],
        "summary": "Trending WebSocket streaming",
        "description": "Real-time trending topic events via WebSocket. Receives JSON messages when new trending tweets are detected in your subscribed categories.",
        "operationId": "trendingWsStream",
        "parameters": [
          {
            "name": "api_key",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Your Trending API key (trend_ prefix)"
          }
        ],
        "responses": {
          "101": {
            "description": "WebSocket upgrade successful"
          },
          "403": {
            "description": "Invalid API key"
          }
        }
      }
    },
    "/v1/pf/targets": {
      "get": {
        "tags": [
          "PumpFun Livestream"
        ],
        "summary": "List watched wallets",
        "description": "Returns all wallet addresses being monitored for pump.fun livestream activity.",
        "operationId": "pfListTargets",
        "security": [
          {
            "pfAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "List of watched wallets",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/PfWatchedWallet"
                      }
                    }
                  }
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": [
          "PumpFun Livestream"
        ],
        "summary": "Add watched wallet",
        "description": "Start monitoring a Solana wallet address for pump.fun livestream starts and ends.",
        "operationId": "pfAddTarget",
        "security": [
          {
            "pfAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "wallet_address"
                ],
                "properties": {
                  "wallet_address": {
                    "type": "string",
                    "example": "DYw8j..."
                  },
                  "label": {
                    "type": "string",
                    "description": "Optional label for this wallet"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Wallet added to watchlist"
          },
          "403": {
            "description": "Wallet limit reached for subscription"
          }
        }
      }
    },
    "/v1/pf/targets/{wallet}": {
      "delete": {
        "tags": [
          "PumpFun Livestream"
        ],
        "summary": "Remove watched wallet",
        "operationId": "pfRemoveTarget",
        "security": [
          {
            "pfAuth": []
          }
        ],
        "parameters": [
          {
            "name": "wallet",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Wallet removed"
          }
        }
      }
    },
    "/v1/pf/events": {
      "get": {
        "tags": [
          "PumpFun Livestream"
        ],
        "summary": "Get recent events",
        "description": "Returns up to 50 most recent livestream events (starts and ends) for your watched wallets.",
        "operationId": "pfGetEvents",
        "security": [
          {
            "pfAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Recent events",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/PfLivestreamEvent"
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/pf/webhook": {
      "get": {
        "tags": [
          "PumpFun Livestream"
        ],
        "summary": "Get PF webhook",
        "operationId": "pfGetWebhook",
        "security": [
          {
            "pfAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Webhook configuration"
          }
        }
      },
      "put": {
        "tags": [
          "PumpFun Livestream"
        ],
        "summary": "Set PF webhook",
        "description": "Configure a webhook URL to receive livestream start/end notifications.",
        "operationId": "pfSetWebhook",
        "security": [
          {
            "pfAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "url"
                ],
                "properties": {
                  "url": {
                    "type": "string",
                    "format": "uri"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Webhook set with signing secret"
          }
        }
      }
    },
    "/v1/pf/status": {
      "get": {
        "tags": [
          "PumpFun Livestream"
        ],
        "summary": "Get PF status",
        "description": "Returns subscription status including wallets watched, max wallet limit, and active add-ons.",
        "operationId": "pfGetStatus",
        "security": [
          {
            "pfAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "PF status",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "is_subscribed": {
                          "type": "boolean"
                        },
                        "wallets_watched": {
                          "type": "integer"
                        },
                        "max_wallets": {
                          "type": "integer"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/pf/ws": {
      "get": {
        "tags": [
          "PumpFun Livestream"
        ],
        "summary": "PF WebSocket streaming",
        "description": "Real-time pump.fun livestream events via WebSocket. Receives JSON messages when watched wallets start or stop livestreaming.",
        "operationId": "pfWsStream",
        "parameters": [
          {
            "name": "api_key",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Your PF API key (pf_ prefix)"
          }
        ],
        "responses": {
          "101": {
            "description": "WebSocket upgrade successful"
          },
          "403": {
            "description": "Invalid API key"
          }
        }
      }
    },
    "/v1/sa/queries": {
      "get": {
        "tags": [
          "Search Alerts"
        ],
        "summary": "List search queries",
        "description": "Returns all active search keyword queries for the authenticated user.",
        "operationId": "saListQueries",
        "security": [
          {
            "saAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "List of search queries",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/SaQuery"
                      }
                    }
                  }
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": [
          "Search Alerts"
        ],
        "summary": "Add search query",
        "description": "Add a keyword search query to monitor across all of Twitter. Maximum 20 queries. Query text must be 1-200 characters.",
        "operationId": "saAddQuery",
        "security": [
          {
            "saAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "query_text"
                ],
                "properties": {
                  "query_text": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 200,
                    "example": "solana airdrop"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Query added"
          },
          "400": {
            "description": "Invalid query text or max queries reached (20)"
          }
        }
      }
    },
    "/v1/sa/queries/{id}": {
      "delete": {
        "tags": [
          "Search Alerts"
        ],
        "summary": "Remove search query",
        "operationId": "saRemoveQuery",
        "security": [
          {
            "saAuth": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Query removed"
          },
          "404": {
            "description": "Query not found"
          }
        }
      }
    },
    "/v1/sa/webhook": {
      "get": {
        "tags": [
          "Search Alerts"
        ],
        "summary": "Get SA webhook",
        "operationId": "saGetWebhook",
        "security": [
          {
            "saAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Webhook configuration"
          }
        }
      },
      "put": {
        "tags": [
          "Search Alerts"
        ],
        "summary": "Set SA webhook",
        "description": "Configure a webhook URL to receive search alert match notifications.",
        "operationId": "saSetWebhook",
        "security": [
          {
            "saAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "url"
                ],
                "properties": {
                  "url": {
                    "type": "string",
                    "format": "uri"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Webhook set with signing secret"
          }
        }
      }
    },
    "/v1/sa/status": {
      "get": {
        "tags": [
          "Search Alerts"
        ],
        "summary": "Get SA status",
        "description": "Returns Search Alerts subscription status including active status, expiry, query count, and max queries.",
        "operationId": "saGetStatus",
        "security": [
          {
            "saAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "SA status",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "is_active": {
                          "type": "boolean"
                        },
                        "expires_at": {
                          "type": "string",
                          "format": "date-time",
                          "nullable": true
                        },
                        "interval_mins": {
                          "type": "integer",
                          "example": 30
                        },
                        "query_count": {
                          "type": "integer"
                        },
                        "max_queries": {
                          "type": "integer",
                          "example": 20
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/sa/ws": {
      "get": {
        "tags": [
          "Search Alerts"
        ],
        "summary": "SA WebSocket streaming",
        "description": "Real-time search alert match events via WebSocket. Receives JSON messages when new tweets match your keyword queries.",
        "operationId": "saWsStream",
        "parameters": [
          {
            "name": "api_key",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Your SA API key (sa_ prefix)"
          }
        ],
        "responses": {
          "101": {
            "description": "WebSocket upgrade successful"
          },
          "403": {
            "description": "Invalid API key"
          }
        }
      }
    },
    "/v1/dt/realtime/ws": {
      "get": {
        "tags": [
          "Xanguard B2B"
        ],
        "summary": "B2B realtime WebSocket (opcode protocol)",
        "description": "TweetCatcher-compatible realtime stream. Connects via opcode-framed WebSocket protocol: server emits HELLO \u2192 client responds with LOGIN \u2192 server emits READY \u2192 server emits EVENT frames as they arrive. Heartbeat every 30s; client must ACK within 90s or be disconnected. Up to 5 concurrent connections per API key. Stale events (>30s old) are dropped.\n\nSupported event types: `tweet` (new tweets/replies/quotes/retweets), `follow_change` (follow/unfollow events on tracked handles), `profile_change` (bio/name/avatar/pinned tweet changes), `new_followers` (digest of new followers per handle), `twitter.follower.new` (a single new follower in real time, requires the `followers` module \u2014 see `WsEventFollowerNew`), `twitter.tweet.deleted` (a monitored account's tweet was deleted, requires the `realtime` module \u2014 see `WsEventTweetDeleted`).\n\n**Connect URL**: `wss://api.xanguard.tech/v1/dt/realtime/ws`",
        "operationId": "dtRealtimeWsStream",
        "parameters": [],
        "responses": {
          "101": {
            "description": "WebSocket upgrade successful. Server immediately emits OP_HELLO (op=10).",
            "headers": {
              "Upgrade": {
                "schema": {
                  "type": "string",
                  "example": "websocket"
                }
              }
            }
          },
          "401": {
            "description": "LOGIN frame missing api_key, or api_key not found / inactive / expired."
          },
          "429": {
            "description": "Connection limit exceeded (max 5 concurrent per key)."
          }
        },
        "x-codeSamples": [
          {
            "lang": "JavaScript",
            "label": "Browser / Node",
            "source": "const ws = new WebSocket('wss://api.xanguard.tech/v1/dt/realtime/ws');\nlet heartbeat;\nws.onopen = () => console.log('connected');\nws.onmessage = (raw) => {\n  const frame = JSON.parse(raw.data);\n  switch (frame.op) {\n    case 10: // HELLO\n      ws.send(JSON.stringify({ op: 2, d: 'dt_YOUR_API_KEY' })); // LOGIN\n      heartbeat = setInterval(() => ws.send(JSON.stringify({ op: 1 })), frame.d.heartbeat_interval || 30000);\n      break;\n    case 4:  // READY \u2014 auth succeeded\n      console.log('streaming');\n      break;\n    case 0:  // EVENT \u2014 your data\n      console.log(frame.t, frame.d);\n      break;\n    case 11: // HEARTBEAT_ACK\n      break;\n    case 3:  // DISCONNECT\n      console.error('disconnected:', frame.d);\n      break;\n  }\n};\nws.onclose = () => clearInterval(heartbeat);"
          },
          {
            "lang": "Python",
            "label": "asyncio + websockets",
            "source": "import asyncio, json\nimport websockets\n\nasync def stream():\n    async with websockets.connect('wss://api.xanguard.tech/v1/dt/realtime/ws') as ws:\n        hello = json.loads(await ws.recv())          # OP_HELLO (op=10)\n        await ws.send(json.dumps({'op': 2, 'd': 'dt_YOUR_API_KEY'}))  # LOGIN\n        heartbeat_ms = hello['d']['heartbeat_interval']\n        async def hb():\n            while True:\n                await asyncio.sleep(heartbeat_ms / 1000)\n                await ws.send(json.dumps({'op': 1}))\n        asyncio.create_task(hb())\n        async for raw in ws:\n            frame = json.loads(raw)\n            if frame['op'] == 0:                      # EVENT\n                print(frame['t'], frame['d'])\n\nasyncio.run(stream())"
          }
        ]
      }
    },
    "/v1/search": {
      "post": {
        "tags": [
          "CA Search"
        ],
        "summary": "Search tweets",
        "description": "Full tweet search by contract address, ticker, cashtag, or keyword \u2014 the same results as the X search page, as structured JSON. Each call walks the last 24 hours of matches and returns up to 200 tweets with full author and engagement metadata, quote/reply context, and a summary (unique authors, total reach, top callers). B2B add-on: requires a dt_ key with CA Search enabled. Also accepts the X-API-Key header (twitterapi.io-compatible). Limits: 10 requests/sec per key plus a daily plan allowance.",
        "operationId": "caSearch",
        "security": [
          {
            "dtAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "query"
                ],
                "properties": {
                  "query": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 200,
                    "description": "Contract address, $TICKER, cashtag, or keywords."
                  },
                  "cursor": {
                    "type": "string",
                    "description": "Optional. Pass the previous response's next_cursor to continue."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Search results",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CaSearchResponse"
                }
              }
            }
          },
          "400": {
            "description": "Missing or oversized query"
          },
          "401": {
            "description": "Missing or invalid dt_ key"
          },
          "403": {
            "description": "CA Search add-on not enabled on this key"
          },
          "429": {
            "description": "Rate limit or daily allowance exhausted"
          },
          "500": {
            "description": "Upstream search failure \u2014 retry"
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "bearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "description": "API key from /apikey command in @Xanguard_bot"
      },
      "cookieAuth": {
        "type": "apiKey",
        "in": "cookie",
        "name": "xg_session",
        "description": "JWT session cookie from web dashboard login"
      },
      "cwAuth": {
        "type": "http",
        "scheme": "bearer",
        "description": "Community Watch API key (prefixed with cw_) from /apikey in @F_xanguard_bot"
      },
      "ctAuth": {
        "type": "http",
        "scheme": "bearer",
        "description": "Convergence Tracker API key (prefixed with ct_) from /apikey in @T_Xanguard_bot"
      },
      "dtAuth": {
        "type": "http",
        "scheme": "bearer",
        "description": "Xanguard B2B API key (prefixed with dt_) from /apikey in @B2B_Xanguard_bot"
      },
      "ecaAuth": {
        "type": "http",
        "scheme": "bearer",
        "description": "ECA API key (prefixed with eca_) from /apikey in @AnfAlex_bot"
      },
      "etAuth": {
        "type": "http",
        "scheme": "bearer",
        "description": "Engagement Tracker API key (prefixed with et_) from /apikey in @E_Xanguard_bot"
      },
      "trendingAuth": {
        "type": "http",
        "scheme": "bearer",
        "description": "Trending Alerts API key (prefixed with trend_) from /apikey in @Trends_Xanguard_bot"
      },
      "pfAuth": {
        "type": "http",
        "scheme": "bearer",
        "description": "PumpFun Livestream API key (prefixed with pf_) from /apikey in @PF_Xanguard_bot"
      },
      "saAuth": {
        "type": "http",
        "scheme": "bearer",
        "description": "Search Alerts API key (prefixed with sa_) from /apikey in @Xanguard_bot"
      }
    },
    "schemas": {
      "ApiResponse": {
        "type": "object",
        "properties": {
          "ok": {
            "type": "boolean"
          },
          "data": {
            "type": "object"
          },
          "error": {
            "type": "string"
          }
        }
      },
      "AccountListResponse": {
        "type": "object",
        "properties": {
          "ok": {
            "type": "boolean",
            "example": true
          },
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/TrackedAccount"
            }
          }
        }
      },
      "AccountResponse": {
        "type": "object",
        "properties": {
          "ok": {
            "type": "boolean",
            "example": true
          },
          "data": {
            "$ref": "#/components/schemas/TrackedAccount"
          }
        }
      },
      "TrackedAccount": {
        "type": "object",
        "properties": {
          "handle": {
            "type": "string",
            "example": "elonmusk"
          },
          "twitter_id": {
            "type": "string",
            "example": "44196397"
          },
          "listener_id": {
            "type": "integer"
          },
          "muted": {
            "type": "boolean"
          },
          "keywords_include": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "nullable": true
          },
          "keywords_exclude": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "nullable": true
          },
          "added_at": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "WebhookCreatedResponse": {
        "type": "object",
        "properties": {
          "ok": {
            "type": "boolean",
            "example": true
          },
          "data": {
            "type": "object",
            "properties": {
              "id": {
                "type": "integer"
              },
              "url": {
                "type": "string",
                "format": "uri"
              },
              "secret": {
                "type": "string",
                "description": "HMAC-SHA256 secret for verifying webhook signatures"
              },
              "created_at": {
                "type": "string",
                "format": "date-time"
              }
            }
          }
        }
      },
      "TweetEvent": {
        "type": "object",
        "description": "Tweet notification payload delivered via webhook, WebSocket, or REST API",
        "properties": {
          "event": {
            "type": "string",
            "enum": [
              "tweet"
            ],
            "example": "tweet"
          },
          "handle": {
            "type": "string",
            "example": "elonmusk"
          },
          "twitter_id": {
            "type": "string"
          },
          "tweet_id": {
            "type": "string"
          },
          "text": {
            "type": "string"
          },
          "url": {
            "type": "string",
            "format": "uri"
          },
          "is_reply": {
            "type": "boolean"
          },
          "is_quote": {
            "type": "boolean"
          },
          "contract_addresses": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Auto-detected Solana contract addresses"
          },
          "timestamp": {
            "type": "string",
            "format": "date-time"
          },
          "latency_ms": {
            "type": "integer",
            "description": "Detection latency in milliseconds"
          }
        }
      },
      "CwEvent": {
        "type": "object",
        "description": "Community Watch event delivered via webhook or WebSocket",
        "properties": {
          "event_type": {
            "type": "string",
            "enum": [
              "community_joined",
              "community_created",
              "community_renamed",
              "description_changed",
              "followed",
              "new_follower_digest"
            ]
          },
          "handle": {
            "type": "string"
          },
          "community_id": {
            "type": "string"
          },
          "community_name": {
            "type": "string"
          },
          "member_count": {
            "type": "integer"
          },
          "timestamp": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "EcaWatchlistEntry": {
        "type": "object",
        "description": "ECA watchlist entry for token launch matching",
        "properties": {
          "id": {
            "type": "integer"
          },
          "ticker": {
            "type": "string",
            "nullable": true
          },
          "token_name": {
            "type": "string",
            "nullable": true
          },
          "contract_address": {
            "type": "string",
            "nullable": true
          },
          "creator_address": {
            "type": "string",
            "nullable": true
          },
          "expires_at": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "EcaMatch": {
        "type": "object",
        "description": "ECA token launch match event",
        "properties": {
          "id": {
            "type": "integer"
          },
          "mint": {
            "type": "string",
            "description": "Solana token mint address"
          },
          "match_type": {
            "type": "string",
            "description": "How the match was detected (ticker, name, contract, creator)"
          },
          "matched_at": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "EtWatchedTweet": {
        "type": "object",
        "description": "Engagement Tracker watched tweet entry",
        "properties": {
          "id": {
            "type": "integer"
          },
          "tweet_id": {
            "type": "string"
          },
          "label": {
            "type": "string",
            "nullable": true
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "EtEngagement": {
        "type": "object",
        "description": "Tweet engagement counts",
        "properties": {
          "tweet_id": {
            "type": "string"
          },
          "favorite_count": {
            "type": "integer"
          },
          "retweet_count": {
            "type": "integer"
          },
          "reply_count": {
            "type": "integer"
          },
          "quote_count": {
            "type": "integer"
          },
          "bookmark_count": {
            "type": "integer"
          },
          "last_updated": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "TrendingCategory": {
        "type": "object",
        "description": "Trending topic category",
        "properties": {
          "slug": {
            "type": "string",
            "example": "crypto"
          },
          "name": {
            "type": "string",
            "example": "Crypto"
          },
          "subscribed": {
            "type": "boolean"
          }
        }
      },
      "PfWatchedWallet": {
        "type": "object",
        "description": "PumpFun Livestream watched wallet",
        "properties": {
          "wallet_address": {
            "type": "string"
          },
          "label": {
            "type": "string",
            "nullable": true
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "PfLivestreamEvent": {
        "type": "object",
        "description": "PumpFun livestream detection event",
        "properties": {
          "id": {
            "type": "integer"
          },
          "wallet_address": {
            "type": "string"
          },
          "mint": {
            "type": "string",
            "description": "Token mint address"
          },
          "token_name": {
            "type": "string"
          },
          "token_symbol": {
            "type": "string"
          },
          "event_type": {
            "type": "string",
            "enum": [
              "livestream_started",
              "livestream_ended"
            ]
          },
          "detected_at": {
            "type": "string",
            "format": "date-time"
          },
          "delivery_latency_ms": {
            "type": "integer"
          }
        }
      },
      "SaQuery": {
        "type": "object",
        "description": "Search Alerts keyword query",
        "properties": {
          "id": {
            "type": "integer"
          },
          "query_text": {
            "type": "string",
            "example": "solana airdrop"
          },
          "interval_mins": {
            "type": "integer",
            "example": 30
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "SaMatchEvent": {
        "type": "object",
        "description": "Search Alerts match event delivered via webhook or WebSocket",
        "properties": {
          "query_id": {
            "type": "integer"
          },
          "query_text": {
            "type": "string"
          },
          "tweet_id": {
            "type": "string"
          },
          "full_text": {
            "type": "string"
          },
          "screen_name": {
            "type": "string"
          },
          "display_name": {
            "type": "string"
          }
        }
      },
      "WsFrameHello": {
        "type": "object",
        "description": "Server \u2192 client. First frame after WebSocket upgrade.",
        "required": [
          "op",
          "d"
        ],
        "properties": {
          "op": {
            "type": "integer",
            "enum": [
              10
            ],
            "description": "OP_HELLO"
          },
          "d": {
            "type": "object",
            "properties": {
              "heartbeat_interval": {
                "type": "integer",
                "example": 30000,
                "description": "milliseconds between heartbeats"
              }
            }
          }
        }
      },
      "WsFrameLogin": {
        "type": "object",
        "description": "Client \u2192 server. Sent in response to HELLO. Must be sent within 15s of upgrade.",
        "required": [
          "op",
          "d"
        ],
        "properties": {
          "op": {
            "type": "integer",
            "enum": [
              2
            ],
            "description": "OP_LOGIN"
          },
          "d": {
            "type": "string",
            "description": "Your API key (dt_ prefix). The literal key string, NOT a Bearer header.",
            "example": "dt_abc123..."
          }
        }
      },
      "WsFrameReady": {
        "type": "object",
        "description": "Server \u2192 client. Sent after successful LOGIN. Streaming begins immediately after.",
        "properties": {
          "op": {
            "type": "integer",
            "enum": [
              4
            ]
          },
          "d": {
            "type": "object",
            "properties": {
              "client_id": {
                "type": "integer"
              },
              "tier": {
                "type": "string",
                "example": "rt_100"
              },
              "modules": {
                "type": "array",
                "items": {
                  "type": "string"
                },
                "example": [
                  "realtime",
                  "follows",
                  "profile_watch",
                  "followers"
                ]
              }
            }
          }
        }
      },
      "WsFrameEvent": {
        "type": "object",
        "description": "Server \u2192 client. Streaming event.",
        "required": [
          "op",
          "t",
          "d"
        ],
        "properties": {
          "op": {
            "type": "integer",
            "enum": [
              0
            ]
          },
          "t": {
            "type": "string",
            "enum": [
              "tweet",
              "follow_change",
              "profile_change",
              "new_followers"
            ]
          },
          "d": {
            "type": "object",
            "description": "Event-specific payload, see schema for each event type"
          }
        }
      },
      "WsFrameHeartbeat": {
        "type": "object",
        "description": "Client \u2192 server. Send every heartbeat_interval ms (default 30s). Server must ACK within 90s or it disconnects you.",
        "properties": {
          "op": {
            "type": "integer",
            "enum": [
              1
            ]
          }
        }
      },
      "WsFrameHeartbeatAck": {
        "type": "object",
        "description": "Server \u2192 client.",
        "properties": {
          "op": {
            "type": "integer",
            "enum": [
              11
            ]
          }
        }
      },
      "WsFrameDisconnect": {
        "type": "object",
        "description": "Server \u2192 client. Connection will close immediately after this frame.",
        "properties": {
          "op": {
            "type": "integer",
            "enum": [
              3
            ]
          },
          "d": {
            "type": "string",
            "description": "human-readable reason"
          }
        }
      },
      "WsEventTweet": {
        "type": "object",
        "description": "Payload for `t=tweet` event.",
        "properties": {
          "tweet_id": {
            "type": "string"
          },
          "author": {
            "type": "object",
            "properties": {
              "handle": {
                "type": "string"
              },
              "twitter_user_id": {
                "type": "string"
              },
              "display_name": {
                "type": "string"
              },
              "avatar_url": {
                "type": "string"
              }
            }
          },
          "text": {
            "type": "string"
          },
          "url": {
            "type": "string"
          },
          "is_reply": {
            "type": "boolean"
          },
          "is_quote": {
            "type": "boolean"
          },
          "is_retweet": {
            "type": "boolean"
          },
          "image_urls": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "mentions": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "WsEventFollowChange": {
        "type": "object",
        "description": "Payload for `t=follow_change` event.",
        "properties": {
          "actor_handle": {
            "type": "string",
            "description": "the tracked handle that did the follow/unfollow"
          },
          "target_handle": {
            "type": "string",
            "description": "the account that was followed/unfollowed"
          },
          "kind": {
            "type": "string",
            "enum": [
              "follow",
              "unfollow"
            ]
          },
          "detected_at": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "WsEventProfileChange": {
        "type": "object",
        "description": "Payload for `t=profile_change` event.",
        "properties": {
          "handle": {
            "type": "string"
          },
          "field": {
            "type": "string",
            "enum": [
              "display_name",
              "bio",
              "avatar_url",
              "banner_url",
              "pinned_tweet_id",
              "location",
              "website"
            ]
          },
          "old_value": {
            "type": "string",
            "nullable": true
          },
          "new_value": {
            "type": "string",
            "nullable": true
          },
          "detected_at": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "WsEventNewFollowers": {
        "type": "object",
        "description": "Payload for `t=new_followers` event. Digest emitted every ~30 minutes per tracked handle.",
        "properties": {
          "handle": {
            "type": "string"
          },
          "new_count": {
            "type": "integer"
          },
          "new_followers": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "handle": {
                  "type": "string"
                },
                "twitter_user_id": {
                  "type": "string"
                },
                "display_name": {
                  "type": "string"
                },
                "follower_count": {
                  "type": "integer"
                }
              }
            }
          },
          "detected_at": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "WsEventFollowerNew": {
        "type": "object",
        "description": "WebSocket frame for a newly detected follower on a monitored account. Delivered in real time as a single follower (not a digest). Requires the `followers` module. Frame shape: `{ \"op\": 0, \"d\": { ... } }`.",
        "required": [
          "op",
          "d"
        ],
        "properties": {
          "op": {
            "type": "integer",
            "enum": [
              0
            ],
            "description": "OP_EVENT"
          },
          "d": {
            "type": "object",
            "required": [
              "event",
              "task_info",
              "data"
            ],
            "properties": {
              "event": {
                "type": "string",
                "enum": [
                  "twitter.follower.new"
                ],
                "example": "twitter.follower.new"
              },
              "task_info": {
                "type": "object",
                "description": "Identifies which monitored account this event belongs to.",
                "properties": {
                  "handle": {
                    "type": "string",
                    "description": "The monitored account that gained a follower.",
                    "example": "elonmusk"
                  }
                }
              },
              "data": {
                "type": "object",
                "description": "The new follower.",
                "properties": {
                  "id": {
                    "type": "string",
                    "description": "Follower's Twitter user ID."
                  },
                  "handle": {
                    "type": "string",
                    "description": "Follower's @handle."
                  },
                  "name": {
                    "type": "string",
                    "nullable": true,
                    "description": "Follower's display name. May be null."
                  }
                }
              }
            }
          }
        }
      },
      "WsEventTweetDeleted": {
        "type": "object",
        "description": "WebSocket frame emitted when a tweet from a monitored account is detected as deleted. WebSocket only \u2014 there is no webhook for this event. Requires the `realtime` module. Frame shape: `{ \"op\": 0, \"d\": { ... } }`.",
        "required": [
          "op",
          "d"
        ],
        "properties": {
          "op": {
            "type": "integer",
            "enum": [
              0
            ],
            "description": "OP_EVENT"
          },
          "d": {
            "type": "object",
            "required": [
              "event",
              "task_info",
              "data"
            ],
            "properties": {
              "event": {
                "type": "string",
                "enum": [
                  "twitter.tweet.deleted"
                ],
                "example": "twitter.tweet.deleted"
              },
              "task_info": {
                "type": "object",
                "description": "Identifies which monitored account this event belongs to.",
                "properties": {
                  "handle": {
                    "type": "string",
                    "description": "The monitored account whose tweet was deleted.",
                    "example": "elonmusk"
                  }
                }
              },
              "data": {
                "type": "object",
                "description": "The deleted tweet reference.",
                "properties": {
                  "tweet_id": {
                    "type": "string",
                    "nullable": true,
                    "description": "ID of the deleted tweet. May be null."
                  }
                }
              }
            }
          }
        }
      },
      "WebhookNewFollowers": {
        "type": "object",
        "description": "Webhook payload posted when new followers are detected for a monitored account. Delivered inside the standard webhook envelope (`X-Signature` HMAC-SHA256). Requires the `followers` module.",
        "required": [
          "event",
          "data"
        ],
        "properties": {
          "event": {
            "type": "string",
            "enum": [
              "new_followers"
            ],
            "example": "new_followers"
          },
          "data": {
            "type": "object",
            "required": [
              "screen_name",
              "twitter_user_id",
              "detected_at",
              "followers"
            ],
            "properties": {
              "screen_name": {
                "type": "string",
                "description": "The monitored account that gained followers."
              },
              "twitter_user_id": {
                "type": "string",
                "description": "Twitter user ID of the monitored account."
              },
              "detected_at": {
                "type": "integer",
                "description": "Detection time, milliseconds since epoch."
              },
              "followers": {
                "type": "array",
                "description": "The newly detected followers.",
                "items": {
                  "type": "object",
                  "properties": {
                    "user_id": {
                      "type": "string"
                    },
                    "screen_name": {
                      "type": "string"
                    },
                    "display_name": {
                      "type": "string"
                    },
                    "followers_count": {
                      "type": "integer"
                    },
                    "following_count": {
                      "type": "integer"
                    },
                    "account_age_days": {
                      "type": "integer",
                      "nullable": true,
                      "description": "Age of the follower's account in days. May be null."
                    }
                  }
                }
              }
            }
          }
        }
      },
      "WebhookEnvelope": {
        "type": "object",
        "description": "All webhook deliveries share this envelope. The HTTP request includes the header `X-Signature: <hex>` containing HMAC-SHA256(secret, raw_body). Receivers MUST verify the signature. Retries: 3 attempts (1s, 2s, 4s). Auto-disable: after 10 consecutive failures the webhook URL is paused.",
        "required": [
          "event",
          "timestamp",
          "data"
        ],
        "properties": {
          "event": {
            "type": "string",
            "enum": [
              "tweet",
              "follow_change",
              "profile_change",
              "new_followers",
              "community_change",
              "engagement_milestone"
            ]
          },
          "timestamp": {
            "type": "integer",
            "description": "milliseconds since epoch"
          },
          "data": {
            "type": "object",
            "description": "Event-specific payload, identical schema to the corresponding WS event."
          }
        }
      },
      "CaSearchAuthor": {
        "type": "object",
        "description": "Full author profile (twitterapi.io-compatible shape).",
        "properties": {
          "userName": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "id": {
            "type": "string"
          },
          "followers": {
            "type": "integer"
          },
          "following": {
            "type": "integer"
          },
          "isBlueVerified": {
            "type": "boolean"
          },
          "profilePicture": {
            "type": "string"
          },
          "description": {
            "type": "string"
          },
          "location": {
            "type": "string"
          },
          "createdAt": {
            "type": "string"
          },
          "statusesCount": {
            "type": "integer"
          },
          "mediaCount": {
            "type": "integer"
          },
          "favouritesCount": {
            "type": "integer"
          }
        }
      },
      "CaSearchTweet": {
        "type": "object",
        "description": "Tweet with full engagement metrics, author object, and quote/reply context.",
        "properties": {
          "type": {
            "type": "string",
            "example": "tweet"
          },
          "id": {
            "type": "string"
          },
          "url": {
            "type": "string"
          },
          "text": {
            "type": "string"
          },
          "createdAt": {
            "type": "string",
            "example": "Sun Jul 20 10:15:00 +0000 2026"
          },
          "retweetCount": {
            "type": "integer"
          },
          "replyCount": {
            "type": "integer"
          },
          "likeCount": {
            "type": "integer"
          },
          "quoteCount": {
            "type": "integer"
          },
          "viewCount": {
            "type": "integer"
          },
          "bookmarkCount": {
            "type": "integer"
          },
          "lang": {
            "type": "string"
          },
          "isReply": {
            "type": "boolean"
          },
          "inReplyToId": {
            "type": "string"
          },
          "inReplyToUsername": {
            "type": "string"
          },
          "conversationId": {
            "type": "string"
          },
          "author": {
            "$ref": "#/components/schemas/CaSearchAuthor"
          },
          "entities": {
            "type": "object"
          },
          "quoted_tweet": {
            "type": [
              "object",
              "null"
            ],
            "description": "Nested tweet object when this tweet quotes another."
          },
          "retweeted_tweet": {
            "type": [
              "object",
              "null"
            ],
            "description": "Nested tweet object when this is a repost."
          },
          "original": {
            "type": [
              "object",
              "null"
            ],
            "description": "Parent tweet (id, text, author) when this is a reply."
          }
        }
      },
      "CaSearchSummary": {
        "type": "object",
        "properties": {
          "total_tweets": {
            "type": "integer"
          },
          "unique_authors": {
            "type": "integer"
          },
          "total_reach": {
            "type": "integer",
            "description": "Combined follower count of all authors."
          },
          "top_callers": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Top 5 authors by followers."
          }
        }
      },
      "CaSearchResponse": {
        "type": "object",
        "properties": {
          "tweets": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/CaSearchTweet"
            }
          },
          "summary": {
            "$ref": "#/components/schemas/CaSearchSummary"
          },
          "window_hours": {
            "type": "integer",
            "example": 24
          },
          "has_next_page": {
            "type": "boolean"
          },
          "next_cursor": {
            "type": [
              "string",
              "null"
            ],
            "description": "Pass as cursor to continue a truncated result set."
          }
        }
      }
    }
  }
}