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
Buckets are keyed on (client IP, API key). Reads: 1200/min (20/s), GET list, health, keys, tweet lookup, resolve. Writes: 600/min (10/s), POST / DELETE add, remove, admin mutations. Errors use 401 / 403 / 429. Bulk add/remove accept up to 200 identifiers per request; more than 200 returns 400.
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" }