Tweet metadata, updates, and lifecycle
Replace live metadata snapshots and merge updates by (platform, tweetId), then apply lifecycle operations without replacing stored content.
tweet/meta
A live metadata payload is the latest snapshot for its post. Replace the previous metadata so omitted fields are cleared. History returns the stored enrichment attached to its row. During recovery, use it only when local metadata is empty; do not overwrite a live snapshot.
Tweet metadata type
typescripttype TweetMeta = {
tweetId: string;
// Pair with tweetId when merging enrichment. When omitted, use twitter.
platform?: 'twitter' | 'truth_social' | 'binance_square';
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'>;
}>;
};
};{
"v": 1,
"t": "tweet",
"op": "meta",
"id": "1234567890",
"ts": 1702500001000,
"d": {
"tweetId": "1234567890",
"platform": "twitter",
"ocr": {
"text": "Chart showing SOL breakout at $100"
},
"detected": {
"tokens": [
{
"symbol": "SOL",
"name": "Solana",
"priceUsd": 98.50,
"sources": ["text", "ocr"]
}
]
}
}
}tweet/update
Apply every update by (platform, tweetId). Keep absent fields; replace an included ref snapshot. Reprocess the updated post.
Tweet update type
Show full definitions (141 lines)
type VerifiedType = 'blue' | 'business' | 'government' | 'verified' | 'none';
type TweetVerifiedLabel = {
badge: string | null;
description: string;
url: string | null;
};
type TweetAuthor = {
banner?: string;
bio?: string;
followersCount?: number;
followingCount?: number;
id?: string;
joinedAt?: number;
location?: string;
metrics?: {
likes?: number;
tweets?: number;
};
// Includes a leading @ when present, for example "@elonmusk".
handle?: string;
name?: string;
platform?: 'twitter' | 'truth_social' | 'binance_square';
profileImage?: string;
// The account's own website, when it has one.
url?: string;
verifiedLabel?: TweetVerifiedLabel;
verifiedType?: VerifiedType;
};
type Media = {
url: string;
} & (
| {
type: 'video';
// Every video is a progressive MP4. A public still poster is included
// when available.
thumbnail?: string;
}
| {
type?: 'image' | 'gif';
thumbnail?: string;
}
);
type TweetUrl = {
url: string;
name?: string;
tco?: string;
};
type TweetMention = {
handle?: string;
id?: string;
name?: string;
};
type TweetArticle = {
description?: string;
id?: string;
publishedAt?: number;
text?: string;
thumbnail?: string;
title: string;
updatedAt?: number;
url: string;
};
type TweetPollChoice = {
id?: string;
image?: string;
label: string;
votes?: number;
};
type TweetPoll = {
choices: TweetPollChoice[];
endsAt?: number;
totalVotes?: number;
updatedAt?: number;
};
type TweetContentKind = 'post' | 'reply' | 'quote' | 'retweet';
type TweetReference = {
article?: TweetArticle;
type: 'reply' | 'quote' | 'retweet';
tweetId: string;
text?: string;
translatedText?: string;
author?: TweetAuthor;
media?: Media[];
poll?: TweetPoll;
quoted?: TweetReference;
subtweet?: TweetReference;
};
type TweetContent = {
tweetId: string;
kind: TweetContentKind;
// Original tweet text when the event includes both original and translated text.
text: string;
// Translation, present only when available.
translatedText?: string;
createdAt: number;
author: TweetAuthor;
article?: TweetArticle;
link?: string;
media?: Media[];
mentions?: TweetMention[];
poll?: TweetPoll;
receivedAt?: number;
urls?: TweetUrl[];
ref?: TweetReference;
};
type TweetUpdate = {
tweetId: string;
// Pair with tweetId. When absent, use author.platform, then twitter.
platform?: 'twitter' | 'truth_social' | 'binance_square';
article?: TweetArticle;
kind?: TweetContentKind;
translatedText?: string;
author?: TweetAuthor;
media?: Media[];
mentions?: TweetMention[];
poll?: TweetPoll;
receivedAt?: number;
urls?: TweetUrl[];
ref?: TweetReference;
} & (
| {
text?: string;
textUpdateType?: never;
}
| {
text: string;
// Supplies the full text of a previously shortened post. Not an edit.
textUpdateType: 'completion';
}
);{
"v": 1,
"t": "tweet",
"op": "update",
"id": "1234567890",
"ts": 1702500000180,
"d": {
"tweetId": "1234567890",
"platform": "twitter",
"ref": {
"type": "reply",
"tweetId": "1234567880",
"text": "Mainnet is ready for launch."
}
}
}{
"v": 1,
"t": "tweet",
"op": "update",
"id": "1234567890",
"ts": 1702500000240,
"d": {
"tweetId": "1234567890",
"platform": "twitter",
"ref": {
"type": "reply",
"tweetId": "1234567880",
"text": "Mainnet is ready for launch.",
"author": {
"handle": "@projectteam",
"name": "Project Team"
},
"subtweet": {
"type": "quote",
"tweetId": "1234567800",
"text": "Launch proposal and contract details.",
"author": {
"handle": "@projectteam",
"name": "Project Team"
}
}
}
}
}Lifecycle events
Lifecycle operations update a known post and do not replace its stored content.
Tweet lifecycle types
Show full definitions (152 lines)
type VerifiedType = 'blue' | 'business' | 'government' | 'verified' | 'none';
type TweetVerifiedLabel = {
badge: string | null;
description: string;
url: string | null;
};
type TweetAuthor = {
banner?: string;
bio?: string;
followersCount?: number;
followingCount?: number;
id?: string;
joinedAt?: number;
location?: string;
metrics?: {
likes?: number;
tweets?: number;
};
// Includes a leading @ when present, for example "@elonmusk".
handle?: string;
name?: string;
platform?: 'twitter' | 'truth_social' | 'binance_square';
profileImage?: string;
// The account's own website, when it has one.
url?: string;
verifiedLabel?: TweetVerifiedLabel;
verifiedType?: VerifiedType;
};
type Media = {
url: string;
} & (
| {
type: 'video';
// Every video is a progressive MP4. A public still poster is included
// when available.
thumbnail?: string;
}
| {
type?: 'image' | 'gif';
thumbnail?: string;
}
);
type TweetUrl = {
url: string;
name?: string;
tco?: string;
};
type TweetMention = {
handle?: string;
id?: string;
name?: string;
};
type TweetArticle = {
description?: string;
id?: string;
publishedAt?: number;
text?: string;
thumbnail?: string;
title: string;
updatedAt?: number;
url: string;
};
type TweetPollChoice = {
id?: string;
image?: string;
label: string;
votes?: number;
};
type TweetPoll = {
choices: TweetPollChoice[];
endsAt?: number;
totalVotes?: number;
updatedAt?: number;
};
type TweetContentKind = 'post' | 'reply' | 'quote' | 'retweet';
type TweetReference = {
article?: TweetArticle;
type: 'reply' | 'quote' | 'retweet';
tweetId: string;
text?: string;
translatedText?: string;
author?: TweetAuthor;
media?: Media[];
poll?: TweetPoll;
quoted?: TweetReference;
subtweet?: TweetReference;
};
type TweetContent = {
tweetId: string;
kind: TweetContentKind;
// Original tweet text when the event includes both original and translated text.
text: string;
// Translation, present only when available.
translatedText?: string;
createdAt: number;
author: TweetAuthor;
article?: TweetArticle;
link?: string;
media?: Media[];
mentions?: TweetMention[];
poll?: TweetPoll;
receivedAt?: number;
urls?: TweetUrl[];
ref?: TweetReference;
};
type TweetDeleteEvent = {
tweetId: string;
// When absent, use author.platform, then twitter.
platform?: 'twitter' | 'truth_social' | 'binance_square';
eventId?: string;
deletedAt?: number;
receivedAt?: number;
author?: TweetAuthor;
text?: string;
};
type TweetPinEvent = {
tweetId: string;
// When absent, use tweet.author.platform or author.platform, then twitter.
platform?: 'twitter' | 'truth_social' | 'binance_square';
eventId: string;
observedAt: number;
receivedAt?: number;
action: 'pin';
author: TweetAuthor;
text?: string;
tweet?: TweetContent;
};
type TweetUnpinEvent = {
tweetId: string;
// When absent, use tweet.author.platform or author.platform, then twitter.
platform?: 'twitter' | 'truth_social' | 'binance_square';
eventId: string;
observedAt: number;
receivedAt?: number;
action: 'unpin';
author: TweetAuthor;
text?: string;
tweet?: TweetContent;
};tweet/delete
Mark the post deleted when this event is observed.
{
"v": 1,
"t": "tweet",
"op": "delete",
"id": "tweet-delete",
"ts": 1772000001060,
"d": {
"eventId": "delete.29043b5a1a4415618c95",
"tweetId": "tweet-delete",
"platform": "twitter",
"author": {
"id": "10228272",
"handle": "@TeamYouTube"
},
"deletedAt": 1772000001050,
"receivedAt": 1772000001050,
"text": "deleted"
}
}tweet/pin
Mark the post pinned and retain any included post snapshot.
Tweet pin event
json{
"v": 1,
"t": "tweet",
"op": "pin",
"id": "tweet-pin",
"ts": 1772000001060,
"d": {
"action": "pin",
"author": {
"id": "10228272",
"handle": "@TeamYouTube"
},
"eventId": "pin.ab70542b9aa6bec229ef",
"observedAt": 1772000001050,
"tweetId": "tweet-pin",
"platform": "twitter",
"receivedAt": 1772000001050,
"text": "pinned"
}
}tweet/unpin
Remove the pinned state for the identified post.
{
"v": 1,
"t": "tweet",
"op": "unpin",
"id": "tweet-unpin",
"ts": 1772000001060,
"d": {
"action": "unpin",
"author": {
"id": "10228272",
"handle": "@TeamYouTube"
},
"eventId": "unpin.0bef09a9f46866cd26d7",
"observedAt": 1772000001050,
"tweetId": "tweet-unpin",
"platform": "twitter",
"receivedAt": 1772000001050,
"text": "unpinned"
}
}