Payloads, Token Detection & OCR

Complete reference for TweetStream alert data structures and enrichment features

Tweet Lifecycle

For tweet events, TweetStream sends a base content message first, optional update messages, and a meta message when enrichment is ready:

  • content - The tweet text, author, and media (arrives first)
  • update - Optional ref context or URL expansion updates
  • meta - Enrichment data: OCR results, detected tokens, markets (arrives shortly after)

Message Families

TweetStream uses one WebSocket envelope format for live events and a separate history response shape for replay:

  • tweet - tweet envelopes carry content, update, and meta events
  • account - account envelopes carry profile_update and follow events
  • control - control envelopes carry handle-management results such as twitter_handles_result
  • /api/history - the history API returns rows with tweetId, body, time, receivedTime, link, messageType, twitterHandle, twitterId, content, and optional meta

Tweet Content Type

type VerifiedType = 'blue' | 'business' | 'government' | 'none';

type TweetAuthor = {
  id?: string;
  handle?: string;
  name?: string;
  platform?: 'twitter' | 'truth_social';
  profileImage?: string;
  followersCount?: number;
  verifiedType?: VerifiedType;
};

type Media = {
  url: string;
  type?: 'image' | 'video' | 'gif';
  thumbnail?: string;
};

type TweetContent = {
  tweetId: string;
  text: string;
  createdAt: number;
  author: TweetAuthor;
  link?: string;
  media?: Media[];
  ref?: {
    type: 'reply' | 'quote' | 'retweet';
    tweetId?: string;
    text?: string;
    author?: TweetAuthor;
    media?: Media[];
  };
};

Truth Social posts use the same tweet content shape. Check author.platform to distinguish them from X/Twitter posts.

Account Event Types

Profile updates and follow notifications use the account envelope family and share the richer actor fields shown below:

type AccountEventActor = TweetAuthor & {
  banner?: string;
  bio?: string;
  location?: string;
  url?: string;
  websiteUrl?: string;
  followingCount?: number;
};

type ProfileUpdateEvent = {
  kind: 'PROFILE';
  eventId: string;
  observedAt: number;
  actor: AccountEventActor;
  changes: {
    avatar?: string;
    banner?: string;
    bio?: string;
    handle?: string;
    location?: string;
    name?: string;
  };
  previous?: {
    avatar?: string;
    banner?: string;
    bio?: string;
    handle?: string;
    location?: string;
    name?: string;
  };
};

type FollowEvent = {
  kind: 'FOLLOW';
  eventId: string;
  observedAt: number;
  actor: AccountEventActor;
  target: AccountEventActor;
};

Tweet Meta Type

The meta payload contains all enrichment data:

type TweetMeta = {
  tweetId: string;
  ocr?: {
    text: string;
  };
  detected?: {
    tokens?: Array<{
      symbol?: string;
      name?: string;
      contract?: string;
      chain?: string;
      networkId?: number;
      priceUsd?: number;
      sources: Array<'text' | 'ocr'>;
    }>;
    cex?: Array<{
      exchange: 'bybit' | 'binance' | 'hyperliquid';
      symbol?: string;
      priceUsd?: number;
      url?: string;
      baseAsset?: string;
      quoteAsset?: string;
      sources: Array<'text' | 'ocr'>;
    }>;
    prediction?: Array<{
      exchange: 'polymarket' | 'kalshi';
      marketId?: string;
      title?: string;
      priceUsd?: number;
      url?: string;
      sources: Array<'text' | 'ocr'>;
    }>;
  };
};

History Response Type

Historical replay returns tweet, profile, and follow rows in one response shape with metadata filters echoed back.

type VerifiedType = 'blue' | 'business' | 'government' | 'none';

type TweetAuthor = {
  id?: string;
  handle?: string;
  name?: string;
  platform?: 'twitter' | 'truth_social';
  profileImage?: string;
  followersCount?: number;
  verifiedType?: VerifiedType;
};

type AccountEventActor = TweetAuthor & {
  banner?: string;
  bio?: string;
  location?: string;
  url?: string;
  websiteUrl?: string;
  followingCount?: number;
};

type ProfileUpdateEvent = {
  kind: 'PROFILE';
  eventId: string;
  observedAt: number;
  actor: AccountEventActor;
  changes: {
    avatar?: string;
    banner?: string;
    bio?: string;
    handle?: string;
    location?: string;
    name?: string;
  };
  previous?: {
    avatar?: string;
    banner?: string;
    bio?: string;
    handle?: string;
    location?: string;
    name?: string;
  };
};

type FollowEvent = {
  kind: 'FOLLOW';
  eventId: string;
  observedAt: number;
  actor: AccountEventActor;
  target: AccountEventActor;
};

type TweetMeta = {
  tweetId: string;
  ocr?: {
    text: string;
  };
  detected?: {
    tokens?: Array<{
      symbol?: string;
      name?: string;
      contract?: string;
      chain?: string;
      networkId?: number;
      priceUsd?: number;
      sources: Array<'text' | 'ocr'>;
    }>;
    cex?: Array<{
      exchange: 'bybit' | 'binance' | 'hyperliquid';
      symbol?: string;
      priceUsd?: number;
      url?: string;
      baseAsset?: string;
      quoteAsset?: string;
      sources: Array<'text' | 'ocr'>;
    }>;
    prediction?: Array<{
      exchange: 'polymarket' | 'kalshi';
      marketId?: string;
      title?: string;
      priceUsd?: number;
      url?: string;
      sources: Array<'text' | 'ocr'>;
    }>;
  };
};

type HistoryMedia = {
  url: string;
  type?: 'image' | 'video' | 'gif';
};

type TweetContent = {
  tweetId: string;
  text: string;
  createdAt: number;
  author: TweetAuthor;
  link?: string;
  media?: HistoryMedia[];
  ref?: {
    type: 'reply' | 'quote' | 'retweet';
    tweetId?: string;
    text?: string;
    author?: TweetAuthor;
    media?: HistoryMedia[];
  };
};

type HistoricalContent = TweetContent | ProfileUpdateEvent | FollowEvent;

type HistoricalTweetResponse = {
  tweetId: string;
  twitterId: string;
  twitterHandle: string | null;
  body: string;
  time: string;
  receivedTime: string;
  link: string;
  messageType: 'TWEET' | 'PROFILE' | 'FOLLOW';
  content: HistoricalContent;
  meta?: TweetMeta;
};

type HistoryResult = {
  data: HistoricalTweetResponse[];
  metadata: {
    count: number;
    handle?: string;
    handles?: string[];
    startDate?: string;
    endDate?: string;
    type?: 'TWEET' | 'PROFILE' | 'FOLLOW';
  };
};

Control Event Type

Handle-management responses use the control envelope family. These results arrive after follow or unfollow commands you send over the WebSocket.

type TwitterHandlesResult = {
  action: 'follow' | 'unfollow';
  requestId: string | null;
  results: Array<{
    input: string;
    normalizedHandle?: string;
    twitterId?: string;
    state: string;
    message?: string;
  }>;
  error: string | null;
};

Token Detection

TweetStream automatically detects tokens from multiple sources:

SourceExamples
$TICKER symbols$BTC, $ETH, $SOL
Contract addresses0x... (EVM), pump... (Solana)
DEX URLsdexscreener.com, birdeye.so
OCR textTickers and addresses in images

OCR Text Extraction

Text is automatically extracted from images attached to tweets. This includes:

  • Screenshots of charts and trading terminals
  • Images containing token information
  • Announcements and promotional graphics

OCR results are included in the meta.ocr.text field and are also scanned for token detection.

Prediction Markets

References to Polymarket markets are detected and enriched with live odds. The detected.prediction array includes:

  • Market ID and title
  • Current price (probability)
  • Direct link to the market

Example: Content Envelope

{
  "v": 1,
  "t": "tweet",
  "op": "content",
  "ts": 1702500000000,
  "d": {
    "tweetId": "1234567890",
    "text": "MAKE AMERICA WEALTHY AGAIN!",
    "createdAt": 1702500000000,
    "author": {
      "id": "25073877",
      "handle": "realDonaldTrump",
      "name": "Donald J. Trump",
      "platform": "truth_social",
      "followersCount": 9800000,
      "verifiedType": "government"
    },
    "link": "https://truthsocial.com/@realDonaldTrump/posts/114338322578075372"
  }
}

Example: Meta Envelope

{
  "v": 1,
  "t": "tweet",
  "op": "meta",
  "ts": 1702500001000,
  "d": {
    "tweetId": "1234567890",
    "ocr": {
      "text": "Chart showing SOL breakout at $100"
    },
    "detected": {
      "tokens": [
        {
          "symbol": "SOL",
          "name": "Solana",
          "priceUsd": 98.50,
          "sources": ["text", "ocr"]
        }
      ]
    }
  }
}

Example: Account Envelope

{
  "v": 1,
  "t": "account",
  "op": "profile_update",
  "ts": 1744156801000,
  "d": {
    "kind": "PROFILE",
    "eventId": "profile_1",
    "observedAt": 1744156800000,
    "actor": {
      "id": "123",
      "handle": "tracked",
      "name": "Tracked Account",
      "profileImage": "https://pbs.twimg.com/profile_images/new-avatar_normal.jpg",
      "followersCount": 125000,
      "followingCount": 321,
      "verifiedType": "business",
      "websiteUrl": "https://tracked.example",
      "location": "New York, NY"
    },
    "changes": {
      "avatar": "https://pbs.twimg.com/profile_images/new-avatar_normal.jpg",
      "bio": "Now watching markets 24/7"
    },
    "previous": {
      "avatar": "https://pbs.twimg.com/profile_images/old-avatar_normal.jpg",
      "bio": "Old bio"
    }
  }
}

Example: Control Envelope

{
  "v": 1,
  "t": "control",
  "op": "twitter_handles_result",
  "ts": 1744156802000,
  "d": {
    "action": "follow",
    "requestId": "req_123",
    "results": [
      {
        "input": "newaccount",
        "normalizedHandle": "newaccount",
        "twitterId": "456",
        "state": "FOLLOWING",
        "message": "Now tracking @newaccount"
      }
    ],
    "error": null
  }
}

Example: History Response

{
  "data": [
    {
      "tweetId": "follow_1",
      "twitterId": "123",
      "twitterHandle": "tracked",
      "body": "Followed @newaccount",
      "time": "2026-04-09T01:00:00.000Z",
      "receivedTime": "2026-04-09T01:00:00.500Z",
      "link": "https://x.com/newaccount",
      "messageType": "FOLLOW",
      "content": {
        "kind": "FOLLOW",
        "eventId": "follow_1",
        "observedAt": 1744160400000,
        "actor": {
          "id": "123",
          "handle": "tracked",
          "name": "Tracked Account",
          "followersCount": 125000,
          "followingCount": 321,
          "verifiedType": "business"
        },
        "target": {
          "id": "456",
          "handle": "newaccount",
          "name": "New Account",
          "profileImage": "https://pbs.twimg.com/profile_images/newaccount_normal.jpg",
          "websiteUrl": "https://newaccount.example"
        }
      }
    }
  ],
  "metadata": {
    "count": 1,
    "handle": "tracked",
    "handles": ["tracked"],
    "startDate": "2026-04-01T00:00:00.000Z",
    "endDate": "2026-04-30T23:59:59.999Z",
    "type": "FOLLOW"
  }
}

Start real-time Twitter WebSocket alerts today

WebSocket delivery, OCR, and token detection - no infrastructure to build.

Start 7-Day Trial

From $199/mo · Basic/Elite 7-day trial · OCR + token detection included

Related Pages