X / Twitter
Technical Schema
LATENCY
50-100ms
Twitter API & WebSocket
Integrate Twitter/X tracking, real-time events, and managed accounts via our high-speed global nodes.
Quick links
Base URLs
REST API Base
https://api.1322.ioWebSocket Endpoints
Normal
wss://ws.normal.1322.io/ws/normalUltimate
wss://ws.ultimate.1322.io/ws/ultimateAuthentication
REST API: Send your API key via query key=, header X-API-Key, or Authorization: Bearer <key>.
WebSocket: Same headers, or query token=<key>. Use the key that matches the stream (normal key for normal URL, ultimate key for ultimate URL).
Rate limit
240 requests per minute per IP (and per key when provided). Responses use standard HTTP status codes (401, 403, 429).
WebSocket Guide
Connection Behavior
- • Server → client: Text frames only; each frame is one JSON object (UTF-8).
- • One-way for events: You only need to handle incoming messages. Server sends periodic pings; respond to pongs to avoid timeouts.
- • Filtered: You only receive events for Twitter user IDs in your tracked list for the key you used. Manage tracked accounts via the REST API or Discord; the stream updates automatically.
Event Flow (Tweets)
Tweets arrive progressively across stages, each enriches the previous:
- 1.
tweet.mini.updatefirst event (fastest, includes full author profile) - 2.
tweet.updateenrichment (cards, subtweet chain, metrics, poll, grok) - 3.
tweet.update.expandeduntruncated text, full article body - 4.
tweet.fullfullchain: post with entire reply/quote chain resolved recursively
Other events: tweet.deleted, profile.update, profile.pinned.update, profile.unpinned.update, following.update.
Additive Merge (Recommended)
For the best display, merge stages by tweet.id (snowflake):
- • Use the longest
body.text - • Union all media arrays
- • Keep the deepest
subtweetchain - • Take the highest metric values
- • Never overwrite a populated field with null/empty. A later stage may lack data that an earlier stage had
Hybrid Clients
Hybrid accounts should connect to both endpoints simultaneously:
- • Normal stream: tweet events + profile events + following events
- • Ultimate stream: tweet events (profile/following events may only arrive on normal)
Deduplicate by tweet.id across both streams. Merge stages from both feeds additively for the richest card.
Reconnection
- • On disconnect, reconnect with exponential backoff (1s, 2s, 4s, 8s… capped at 30s).
- • Respond to server pings with pongs to keep the connection alive.
- • No events are queued during disconnection — you may miss events while offline.
WS Data Types & Events
All data types the 1322 WebSocket sends you.
export interface WebsocketWorkerEvent {
id: string; // Unique ID for this event (Can be used for debouncing and deduplication across multiple connections)
type: string; // The type of event being sent
source: "1322"; // Always "1322" — identifies the event origin
}
Tweet Events
export interface MiniTweetUpdate {
type: 'tweet.mini.update';
tweet: TwitterMiniTweet;
}
This is the main event for tweets, this will be the first event for ANY tweet. Meant to be brief information for speed. If the tweet is quote/retweet etc it won't yet contain subtweet information.
export interface TweetUpdate {
type: 'tweet.update';
tweet: TwitterTweet;
}
Used to provide full information on a tweet. Sent ~60ms after tweet.mini.update if the tweet is a quote, reply, retweet, or contains a URL with a card.
export interface TweetUpdateExpanded {
type: 'tweet.update.expanded';
tweet: TwitterTweet;
}
Includes FULL text of any tweet (tweet.update truncates it) and contains info about articles. Only sent if there's an article or truncated text.
export interface DeletedTweet {
type: 'tweet.deleted';
tweet: TwitterTweet; // metrics may be outdated such as likes, replies, retweets, etc
deleted_at: number;
}
export interface TweetFull {
type: 'tweet.full';
tweet: TwitterTweet; // Fullchain: subtweet forms a recursive chain of full tweets
}
Fullchain — entire reply or quote thread resolved in one payload. The root tweet's subtweet is a full TwitterTweet (not null) that links down the chain. Each node has its own subtweet for the next level.
Reply chain: Root → subtweet → Level 2 → subtweet → Level 3 → null Quote chain: Root → subtweet → Quoted → subtweet → Quoted's quote → null Walk subtweet recursively to traverse the full thread. Each node has: author, body, media, metrics, card, poll, article, grok.
Profile & Misc Events
export interface ProfileUpdate {
type: 'profile.update';
user: TwitterUser; // The new profile information for this user
before: TwitterUser; // The old profile information for this user
}
export interface FollowingUpdate {
type: 'following.update';
change: "unfollowed" | "followed";
following: TwitterUser; // The target user who was followed/unfollowed
user: TwitterUser; // The watched user who was detected to have followed the target user
}
export interface WorkerProfilePinnedUpdateEvent extends WebsocketWorkerEvent {
type: 'profile.pinned.update';
user: TwitterUser; // The user who pinned their tweet(s)
pinned: TwitterTweet[]; // The expanded pinned tweet(s) for this user
}
export interface WorkerProfileUnpinnedUpdateEvent extends WebsocketWorkerEvent {
type: 'profile.unpinned.update';
user: TwitterUser; // The user who pinned their tweet(s)
pinned: TwitterTweet[]; // The expanded pinned tweet(s) for this user
}
Types
// Represents a twitter user's account information in complete format
// The TwitterUser interface represents a complete / detailed version of a Twitter / X user's profile.
export interface TwitterUser {
id: string; // The user's account ID
handle: string; // The user's account handle (Without @)
private: boolean; // If the user's account is currently private or not
verified: boolean | VerificationBadge; // Blue check, gold org badge, or boolean shorthand
sensitive: boolean; // If the user's account is marked to contain sensitive information or not
restricted: boolean; // If the user's account is currently restricted for unusual activity or not
joined_at: number; // The UNIX timestamp of when the user joined Twitter in milliseconds
// Contains the user's profile information
profile: {
name: string; // The user's profile display name
location: null | string; // The user's profile location (if one is set)
avatar: null | string; // The user's custom profile avatar url (if one is set)
banner: null | string; // The user's custom profile banner url (if one is set)
pinned: string[]; // The list of pinned tweet IDs (if any are pinned) on the user's profile
// Contains the user's profile custom link information (if one is set)
url: null | {
name: string; // The display name of the link
url: string; // The original URL of the link
tco: string; // The Twitter t.co wrapped URL variant of the link
};
// Contains the user's profile description information
description: {
text: string; // The plain text of the description
// The list of clickable URLs contained in the description
urls: {
name: string; // The display name of the URL
url: string; // The original URL value of the URL
tco: string; // The Twitter t.co wrapped URL variant of the URL
}[];
};
};
// Contains the user's profile metrics information
metrics: {
likes: number; // The number of liked tweets by the user
media: number; // The number of media (images, videos, gifs) posted by the user
tweets: number; // The number of tweets posted by the user
friends: number; // The number of friends of the user (People who follow the user and the user follows them back)
followers: number; // The number of followers of the user
following: number; // The number of accounts followed by the user
};
}
// When verified is an object (instead of boolean), it carries badge tier and optional org linkage
interface VerificationBadge {
type: 'none' | 'blue' | 'gold'; // none=unverified, blue=standard checkmark, gold=organization
label: null | {
description: string; // Affiliated org or business name
badge: string | null; // Badge image URL
url: string | null; // Link to org profile
};
}
// Treat verified: true or type !== 'none' as having a checkmark.
// Use label only when showing org-linked badges.
interface TwitterMiniUser {
id: string;
handle: string;
name?: string;
avatar?: string;
verified?: boolean | VerificationBadge; // boolean for simple check, or object for org badges
profile?: { name: string; avatar: string | null; };
metrics?: { following: number; followers: number; };
}
// Represents a twitter tweet's information in a minimal format
// The TwitterMiniTweet interface represents a brief / compressed version of a Twitter / X post.
export interface TwitterMiniTweet {
id: string; // The tweet's snowflake ID
type: 'TWEET' | 'RETWEET' | 'QUOTE' | 'REPLY'; // The type of the tweet
created_at: number; // The UNIX timestamp of when the tweet was created on Twitter's servers in milliseconds
// The account information of the tweet's author
author: TwitterMiniUser;
// The subtweet (reply, quote, retweet) referenced by this tweet (if any)
subtweet: null | TwitterMiniTweet;
// Contains information about who the tweet is replying to (if any)
reply: null | {
id: string; // The account ID of the user who was replied to
handle: string; // The account handle (Without @) of the user who was replied to
};
// Contains information about who the tweet is quoting (if any)
quoted: null | {
id: string; // The account ID of the user who was quoted
handle: string; // The account handle (Without @) of the user who was quoted
};
// Contains the tweet's body information
body: {
text: string; // The plain text of the tweet body
// The list of clickable URLs contained in the tweet
urls: {
name: string; // The display name of the URL
url: string; // The original URL value of the URL
tco: string; // The Twitter t.co wrapped URL variant of the URL
}[];
// The list of mentioned users in the tweet
mentions: {
id: string; // The mentioned user's account ID
name: string; // The mentioned user's display name
handle: string; // The mentioned user's account handle (Without @)
}[];
};
// Contains information about the tweet's media
media: {
images: string[]; // The list of image URLs in the tweet
videos: string[]; // The list of video URLs in the tweet
thumbnails: string[];
// Note! Proxied media will only be available in certain scenarios
// Fall back to using normal media URLs if proxied URLs are not available
proxied: null | {
images: string[]; // The list of proxied image URLs in the tweet
};
};
}
// Represents a twitter tweet's information in complete format
// The TwitterTweet interface represents a complete / detailed / rich version of a Twitter / X post.
export interface TwitterTweet {
id: string; // The tweet's snowflake ID
type: 'TWEET' | 'RETWEET' | 'QUOTE' | 'REPLY'; // The type of the tweet
created_at: number; // The UNIX timestamp of when the tweet was created on Twitter's servers in milliseconds
// The account information of the tweet's author
author: TwitterUser;
// The subtweet (reply, quote, retweet) referenced by this tweet (if any)
subtweet: null | TwitterTweet;
// Contains information about who the tweet is replying to (if any)
reply: null | {
id: string; // The account ID of the user who was replied to
handle: string; // The account handle (Without @) of the user who was replied to
};
// Contains information about who the tweet is quoting (if any)
quoted: null | {
id: string; // The account ID of the user who was quoted
handle: string; // The account handle (Without @) of the user who was quoted
};
// Contains the tweet's body information
body: {
text: string; // The plain text of the tweet body
// The list of clickable URLs contained in the tweet
urls: {
name: string; // The display name of the URL
url: string; // The original URL value of the URL
tco: string; // The Twitter t.co wrapped URL variant of the URL
}[];
// The list of mentioned users in the tweet
mentions: {
id: string; // The mentioned user's account ID
name: string; // The mentioned user's display name
handle: string; // The mentioned user's account handle (Without @)
}[];
// The list of structured components contained in the tweet body for expanded rich / long tweets (if any)
components: (
| {
// The `text` component represents represents a text part of a long tweet
type: 'text';
text: string; // The plain text of the component
bold: boolean; // If the text is bold or not
italics: boolean; // If the text is italics or not
}
| {
// The `image` component represents represents an image part of a long tweet
type: 'image';
url: string;
}
| {
// The `video` component represents represents a video part of a long tweet
type: 'video';
url: string;
}
)[];
};
// Contains information about the tweet's media
media: {
images: string[]; // The list of image URLs in the tweet
videos: string[]; // The list of video URLs in the tweet
thumbnails: string[]; // The list of video thumbnail URLs in the tweet
// Note! Proxied media will only be available in certain scenarios
// Fall back to using normal media URLs if proxied URLs are not available
proxied: null | {
images: string[]; // The list of proxied image URLs in the tweet
thumbnails: string[]; // The list of proxied thumbnail URLs in the tweet
};
};
// Contains the embedded Grok xAI conversation preview in the tweet (if any)
grok: null | {
id: string; // The ID of the Grok conversation
// The preview information of the Grok conversation (Supports either an answer or generated images)
conversation: {
from: 'USER' | 'AGENT'; // Who is the sender of the message
message: string; // The text of the message
images: string[]; // The list of image URLs in the message
}[];
};
// Contains information about an embedded card within the tweet (if any)
card: null | {
url: string; // The original URL of the card
image: string; // The thumbnail image URL of the card
title: string; // The title text of the card
description: string; // The description text of the card
};
// Contains information about a poll within the tweet (if any)
poll: null | {
ends_at: number; // The UNIX timestamp of when the poll ends in milliseconds
updated_at: number; // The UNIX timestamp of when the poll was last updated in milliseconds
// The list of poll choices
choices: {
label: string; // The label text of the poll choice
count: number; // The number of votes for the poll choice
}[];
};
// Contains information about an article within the tweet (if any)
article: null | {
id: string; // The article's snowflake ID
title: string; // The title text of the article
thumbnail: null | string; // The thumbnail image URL of the article
created_at: number; // The UNIX timestamp of when the article was created in milliseconds
updated_at: number; // The UNIX timestamp of when the article was last updated in milliseconds
// Contains the article's body information
body: {
text: string; // The plain text of the article body
// The list of components represents the rich structured component within the article
// RENDERING: Each component should be rendered as a separate section with double line vertical spacing
components: (
| {
// The `divider` component represents a divider between article sections
// Twitter / X user interface renders this divider as a horizontal gray line
type: 'divider';
}
// The `text` component represents some textual component within the article
| {
type: 'text';
// The `header-one` variant is a large title which separates the article into sections
// The `header-two` variant is a smaller title which separates the article into subsections
// The `paragraph` variant is just regular paragraph text
// The `blockquote` variant is just paragraph text idented by a line to form a quoted block of text
// The `ordered-list` variant is an ordered list with numbering for each line
// The `unordered-list` variant is an unordered list with bullet points for each line
// The `latex-box` variant is a LaTeX equation box used to render mathematical equations (Ex: `$$a^2 + b^2 = c^2$$`)
// The `markdown-box` variant is a Markdown code block used to render code snippets (Ex: `\\`\\`js\nconsole.log('Hello World!');\n\\`\\`\\`)
variant:
| 'header-one'
| 'header-two'
| 'paragraph'
| 'blockquote'
| 'ordered-list'
| 'unordered-list'
| 'latex-box'
| 'markdown-box';
// The list of lines represents the list items of this component
// RENDERING: Each line should be rendered as a separate line with single line vertical spacing
lines: {
// The plain text of this line
// The `styles` array contains unique styling information for parts of the text
// The `urls` array contains unique URLs for parts of the text
text: string;
// The list of styling applied to parts of the text identified by the `from` and `to` indexes
styles: {
from: number; // The starting index of the text which is styled
to: number; // The ending index of the text which is styled
text: 'bold' | 'italics' | 'strikethrough'; // The type of text styling applied
}[];
// The list of clickable hyperlink URLs identified by the `from` and `to` indexes
urls: {
from: number; // The starting index of the text which is a URL
to: number; // The ending index of the text which is a URL
url: string; // The clickable URL link of the text
}[];
}[];
}
// The `media` component represents some visual media within the article
| {
type: 'media';
// The `image` variant is an image media type
// The `gif` variant is a GIF media type
// The `video` variant is a video media type
variant: 'image' | 'gif' | 'video';
url: string; // The media URL for this variant of the media
thumbnail: string; // The media thumbnail URL for this variant of the media
caption: null | string; // The associated caption text (if any)
}
// The `tweet` component represents an embedded tweet within the article
| {
type: 'tweet';
tweet: {
id: string; // The tweet's snowflake ID
url: string; // The tweet's URL
object: null | TwitterTweet; // The tweet object (May need to be fetched separately if null)
};
}
)[];
};
};
// Contains information about the tweet's metrics
metrics: {
likes: number; // The number of likes on the tweet
quotes: number; // The number of quotes on the tweet
replies: number; // The number of replies on the tweet
retweets: number; // The number of retweets on the tweet
// Contains information about the tweet's advanced metrics
// If this is null, then you need to fetch the expanded version of the tweet to get the advanced metrics
advanced: null | {
views: number; // The number of views on the tweet
};
};
// Community block — present when the tweet belongs to a community (fetched with ?full=true)
community?: {
id: string; // Community snowflake ID
name: string; // Community display name
url: string; // Community URL
};
}
Management API
Get tracked accounts
GET /v1/trackedRetrieve all Twitter accounts you are currently tracking.
{
"success": true,
"tier": "normal",
"page": 1,
"trackedAccounts": [
{
"createdAt": "2025-02-13T12:00:00Z",
"twitterId": "44196397",
"twitterUsername": "elonmusk"
}
]
}
Get all keys (Hybrid)
GET /v1/keysReturns all keys associated with your account. Essential for hybrid subscriptions to discover both Normal and Ultimate keys.
{
"plan": "hybrid",
"keys": [
{
"tier": "normal",
"key": "9121dc75-...",
"trackedCount": 800,
"totalLimit": 1500
},
{
"tier": "ultimate",
"key": "a1b2c3d4-...",
"trackedCount": 0,
"totalLimit": 50
}
]
}
Add tracked accounts
POST /v1/trackedAdd one or more Twitter accounts. You can send multiple accounts as a comma-separated list. Usernames and IDs are resolved automatically.
curl -X POST "https://api.1322.io/v1/tracked" \
-H "Content-Type: application/json" \
-H "X-API-Key: YOUR_API_KEY" \
-d '{"identifiers": "elonmusk,@twitter,44196397", "type": "username"}'
{
"success": true,
"message": "processed identifiers",
"tier": "normal",
"results": {
"successful": [
{
"identifier": "elonmusk",
"twitterUsername": "elonmusk",
"twitterId": "44196397",
"trackedAccount": {
"createdAt": "2025-02-13T12:00:00Z",
"twitterId": "44196397",
"twitterUsername": "elonmusk"
}
}
],
"skipped": [],
"failed": []
}
}
Remove tracked accounts
DELETE /v1/trackedRemove one or more Twitter accounts from your tracking list.
curl -X DELETE "https://api.1322.io/v1/tracked" \
-H "Content-Type: application/json" \
-H "X-API-Key: YOUR_API_KEY" \
-d '{"identifiers": "elonmusk,@twitter", "type": "username"}'
{
"success": true,
"message": "processed identifiers",
"tier": "normal",
"results": {
"successful": [{ "identifier": "elonmusk,@twitter" }],
"skipped": [],
"failed": []
}
}
Fetch tweet by ID
GET /v1/data/tweet/:idFetch any tweet by its snowflake ID. Use the full or expanded boolean query parameters to request untruncated text. Returns the full TwitterTweet object.
curl "https://api.1322.io/v1/data/tweet/1234567890123456789?full=true" \
-H "X-API-Key: YOUR_API_KEY"
{
"success": true,
"tweet": {
"id": "1234567890123456789",
"type": "TWEET",
"created_at": 1700000000000,
"author": {
"id": "44196397",
"handle": "elonmusk",
"name": "Elon Musk",
"avatar": "https://pbs.twimg.com/profile_images/..."
},
"body": {
"text": "Full untruncated tweet text here...",
"urls": [],
"mentions": []
},
"media": { "images": [], "videos": [], "thumbnails": [] },
"metrics": { "likes": 15200, "quotes": 340, "replies": 2100, "retweets": 4500 }
}
}
Resolve username
GET /v1/resolve/username/:usernameResolve an X username to a Twitter ID. Returns the user's ID, display name, follower count, and account status.
curl "https://api.1322.io/v1/resolve/username/elonmusk" \
-H "X-API-Key: YOUR_API_KEY"
{
"username": "elonmusk",
"twitterId": "44196397",
"displayName": "Elon Musk",
"followers": 210000000,
"status": "active"
}
Get API health
GET /v1/healthReturns the health status of the API. No authentication required.
{ "status": "ok" }