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 updatesmeta- 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 eventsaccount- account envelopes carry profile_update and follow eventscontrol- 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:
| Source | Examples |
|---|---|
| $TICKER symbols | $BTC, $ETH, $SOL |
| Contract addresses | 0x... (EVM), pump... (Solana) |
| DEX URLs | dexscreener.com, birdeye.so |
| OCR text | Tickers 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 3-Day TrialFrom $199/mo · Basic/Elite 3-day trial · OCR + token detection included
