# 1322 — full machine-readable reference (llms-full.txt) > This file extends https://1322.io/llms.txt with the complete per-platform API reference: REST bases, WebSocket endpoints, authentication, rate limits, management endpoints, event types and type definitions for every 1322 source. Human-readable docs: https://1322.io/docs. MCP server for tool-based access: https://1322.io/mcp. # 1322 — Real-Time Multi-Platform Monitoring APIs > Last updated: 2026-09-26 > [1322](https://1322.io) provides real-time monitored-account feeds for X (Twitter), Truth Social, Instagram, YouTube, TikTok, Binance Square, and 15+ news outlets. Plans start at $150/month (YouTube); X Starter is $250 per month for 100 tracked accounts with WebSocket included; other sources are separate subscriptions. X delivery typically operates in a 150-250ms range over WebSocket (observed, not an SLA). Alerts can also route to Discord, Telegram, signed webhooks, or a custom consumer. ## What 1322 does - Tracks accounts on X (Twitter), Truth Social, Instagram, YouTube, TikTok, Binance Square, and news outlets - Delivers each source's supported events over WebSocket (150-250ms typical for X, observed, not an SLA; source-dependent elsewhere) - REST APIs to add/remove tracked accounts and inspect the current tracked list - Discord bot, Telegram bot, and signed webhook delivery - Self-serve dashboard with live feed, billing, and API key management ## Key pages - [Home](https://1322.io/) - [Chinese overview](https://1322.io/zh) - [Pricing and plans](https://1322.io/pricing) - [Platform overview](https://1322.io/platforms) - [Real-time Twitter WebSocket API](https://1322.io/platforms/x) - [Instagram monitoring API](https://1322.io/platforms/instagram) - [Truth Social monitoring](https://1322.io/platforms/truth) - [Trump Truth Social alerts](https://1322.io/track/trump-truth-social) - [YouTube monitoring](https://1322.io/platforms/youtube) - [TikTok monitoring](https://1322.io/platforms/tiktok) - [Binance Square monitoring](https://1322.io/platforms/binance) - [News monitoring](https://1322.io/platforms/news) - [1322 Signal Observatory and latency methodology](https://1322.io/speed) - [Signal Observatory data (JSON)](https://1322.io/speed/data) - [Signal Observatory data (CSV)](https://1322.io/speed/data?format=csv) - [API documentation](https://1322.io/docs) - [Twitter API alternatives comparison](https://1322.io/compare/twitter-api-alternatives) - [Best crypto Twitter monitoring and tracker tools](https://1322.io/blog/best-crypto-twitter-monitoring-tools) - [Hosted live feed for tracked accounts](https://1322.io/tracked-account-monitoring) - [TikTok API alternatives comparison](https://1322.io/compare/tiktok-api-alternatives) - [How to monitor TikTok creators programmatically](https://1322.io/blog/tiktok-creator-monitoring-api) - [Build a TikTok creator alert bot in Python](https://1322.io/blog/tiktok-alert-bot-python) - [Get notified when a TikTok creator goes live](https://1322.io/track/tiktok-live-alerts) - [TikTok creator desk reference deployment](https://1322.io/case-studies/tiktok-creator-desk) - [Crypto KOL tracking](https://1322.io/use-cases/crypto-kol-tracking) - [Prediction market data feed](https://1322.io/use-cases/prediction-markets) - [Social alerts for trading bots](https://1322.io/use-cases/trading-bot-social-alerts) - [Real-time monitoring for newsrooms](https://1322.io/use-cases/newsroom-monitoring) - [YouTube API alternatives comparison](https://1322.io/compare/youtube-api-alternatives) - [Twitter / X API pricing guide](https://1322.io/blog/twitter-api-pricing) - [How real-time social media monitoring APIs work](https://1322.io/monitoring-api) - [Multi-platform post tracking](https://1322.io/multi-platform-tracking) - [Monitoring API comparisons](https://1322.io/compare) - [Twitter to Discord bot setup](https://1322.io/blog/twitter-to-discord-bot) - [Binance Square signal monitoring](https://1322.io/use-cases/binance-square-signals) - [Use cases](https://1322.io/use-cases) - [Case studies](https://1322.io/case-studies) - [Crypto trading desk reference deployment](https://1322.io/case-studies/crypto-trading-desk) - [Political event desk reference deployment](https://1322.io/case-studies/political-event-desk) - [About 1322](https://1322.io/about) - [Blog](https://1322.io/blog) - [Truth Social API guide](https://1322.io/blog/truth-social-api-guide) - [Twitter Streaming API alternatives guide](https://1322.io/blog/twitter-streaming-api-alternatives) - [KOL tweet alert bot tutorial](https://1322.io/blog/kol-tweet-alert-bot-python) - [Instagram monitoring without the official API](https://1322.io/blog/instagram-monitoring-without-official-api) - [Get Trump's Truth Social posts in Discord or Python](https://1322.io/blog/track-trump-truth-social-posts) - [Monitor Elon Musk's X posts](https://1322.io/track/elon-musk-tweets) - [Trial and evaluation access](https://1322.io/trial) - [Binance Square API guide](https://1322.io/blog/binance-square-api-guide) - [Instagram API alternatives comparison](https://1322.io/compare/instagram-api-alternatives) - [Track Instagram Stories in real time](https://1322.io/blog/instagram-story-tracker) - [Instagram to Discord bot: post and Story alerts setup](https://1322.io/blog/instagram-to-discord-bot) - [Instagram launch monitoring reference deployment](https://1322.io/case-studies/instagram-launch-monitoring) - [Truth Social scraper and API alternatives](https://1322.io/compare/truth-social-api-alternatives) - [Binance Square API alternatives comparison](https://1322.io/compare/binance-square-api-alternatives) - [Discord and Telegram alert bots](https://1322.io/use-cases/discord-telegram-bots) - [Open-source examples](https://github.com/1322monitors/social-monitor-examples) - [Open-source Binance Square monitor](https://github.com/1322monitors/binance-square-realtime) ## Pricing - X monthly plans: Starter $250/mo (100 tracked accounts), Standard $500/mo (250), Professional $800/mo (500), Ultimate $4,000/mo (25 Ultimate-selected accounts plus 350 normal; provisioned via sales); WebSocket delivery included - TikTok monthly plans: $200/mo (5 tracked creators), $350/mo (15), $550/mo (30); Discord bot delivery included, WebSocket delivery is a $100/mo add-on - Truth Social monthly plans: $300/mo (5 tracked accounts), $450/mo (15), $700/mo (30); Discord bot delivery included, WebSocket delivery is a $150/mo add-on - Instagram monthly plans: $300/mo (5 tracked accounts), $550/mo (15), $750/mo (30); Discord bot delivery included, WebSocket delivery is a $150/mo add-on - YouTube monthly plans: $150/mo (5 tracked channels), $300/mo (15), $400/mo (50); Discord bot delivery included, WebSocket delivery is a $100/mo add-on - Binance Square monthly plans: $300/mo (5 tracked accounts), $450/mo (15), $700/mo (30); Discord bot delivery included, WebSocket delivery is a $100/mo add-on - News monthly plan: $350/mo (15+ news providers); Discord bot delivery included, WebSocket delivery is a $100/mo add-on - Instagram, Truth Social, YouTube, TikTok, Binance Square and News monitoring are each available as separate subscriptions - Multi-platform discount: each additional platform bought in the same checkout is $50/month off, applied automatically - Yearly term: 12 months of access for 9 months' price - Custom multi-platform bundles available via Discord or support@1322.io - Payment: crypto checkout, or card with a processing surcharge shown before you pay. Plans are prepaid for a fixed term and do not renew automatically - Evaluation: a one-day trial of the real dashboard and production payloads with a capped tracked list, no card and no purchase commitment, requested through the 1322 Discord (https://1322.io/trial) ## Technical facts - X (Twitter) detection latency: 150-250ms typical (observed, not an SLA), delivered over WebSocket - Selected X Ultimate accounts: around 100ms typical operating average (manual provisioning; not an SLA) - Dedicated Truth Social priority lanes for @realDonaldTrump and @WhiteHouse: around 50ms typical operating average (not an SLA) - Regular Truth Social lanes: 150-250ms typical operating range (not an SLA) - Instagram: around a 350ms median on tracked public accounts (an observed median, not an SLA) - Binance Square, YouTube, TikTok and News: sub-second typical; no millisecond profile is published for them - Observatory disclosure: the animated panel is a privacy-safe synthetic replay constrained to the published profiles; it is not connected to customer traffic or private backend telemetry - Delivery options: WebSocket stream, REST API, Discord bot, Telegram bot, signed webhooks - REST API hosts: api.1322.io (X), truth.1322.io (Truth Social), 1322.io/v1 (Instagram), youtube.1322.io (YouTube), tiktok.1322.io (TikTok), binance.1322.io (Binance Square), newsfeed.1322.io (News) - Real-time TikTok creator monitoring: tracked by username or sec_uid, emitting tiktok.upload.created, tiktok.repost.created, tiktok.live.started and tiktok.live.ended events under the schema 1322.tiktok.event.v1, plus tiktok.media.ready under the smaller schema 1322.tiktok.media.v1 (no account block). TikTok delivery is typically sub-second from publication over WebSocket (an operating range, not an SLA) - TikTok uses two distinct credentials and they must not be mixed: the REST API key and a separate WebSocket key. REST accepts either `X-API-Key: ` or `Authorization: Bearer `. The WebSocket accepts either `X-WS-Key: ` or `Authorization: Bearer `. Sending the API key on the WebSocket (or the WS key on REST) is rejected. The stream URL is `wss://tiktok.1322.io` with an opaque `/ws/<32-hex>` path and no query string — query-string keys are not enabled. Liveness and readiness are public and unauthenticated at `/health`, `/healthz` and `/readyz` (`/v1/health` requires the API key). - TikTok content frames carry `kind` ("video", "photo" or "carousel") so the post type never has to be inferred from media, plus `mentions` and `hashtags` parsed out of the description (hashtags without the leading `#`, mentions without the leading `@`), `duration` in seconds, a `music` object (`title`, `author_name`, `original`, `duration`), `title`, and `image_urls` for photo posts and carousels. `verified` appears on the account, and on a repost's `original_author`, only when that creator is verified and is absent otherwise. There is no `play_url` on a tenant frame — the playable file is `media_url` on the separate `1322.tiktok.media.v1` media-ready frame, a short-lived signed URL that is downloaded as is, with no API key. - Real-time YouTube channel monitoring: tracked by UC-prefixed channel ID, @handle or channel URL, emitting three message types over its WebSocket — `upload` (the primary event, sent for every detected video, with `subtype` "video" or "short"), `upgrade` (conditional: sent only when a later thumbnail retry improves an image that was still unconfirmed at upload time) and `deletion` (an independent later event, emitted once a video is explicitly confirmed unavailable). These are not a guaranteed three-message sequence — most videos produce neither an upgrade nor a deletion, so a consumer should be built around `upload` alone. - YouTube REST accepts either `Authorization: Bearer ` or the `X-Api-Key` header, and the WebSocket accepts either `?key=` on the `ws_url` from `GET /v1/dashboard` or the `X-WS-KEY` header. The tracker serves ten endpoints: `GET /v1/health`, `GET /v1/docs`, `GET /openapi.json`, `GET /v1/status`, `GET /v1/dashboard`, `GET /v1/limits`, `GET /v1/list`, `POST /v1/track`, `POST /v1/untrack` and `GET /v1/ws/status`. `GET /v1/dashboard` is flat and returns a complete `ws_url`. - Independent of the official Twitter API v2 — no Twitter developer account, per-request quotas, or elevated access required - Real-time Instagram monitoring of public accounts (posts, Stories, Reels, carousels): Discord bot delivery included, WebSocket as an add-on; no Meta developer app required - Truth Social events: new truths, retruths and quotes with the quote chain resolved up to a quote of a quote, with their media - Works from any WebSocket-capable language: JavaScript, Python, Go, Rust, and others ## API access - Authentication: REST requests use the platform API key as documented for that service; WebSocket access uses the customer key or signed connection flow documented in the dashboard. Call the APIs from your own server, never from browser code: API keys must stay private, and the REST endpoints are not built for cross-origin (CORS) browser requests. - Rate limits: REST management endpoints are rate-limited per API key; the WebSocket stream is push-based and not polled, so it has no per-request quota. - Full request/response reference, per-platform endpoints and event schemas: [1322 documentation](https://1322.io/docs) - Example X WebSocket event (`tweet.mini.update`, the first message for every new tweet; trimmed). Each source has its own documented contract; see the documentation for the others: ```json { "type": "tweet.mini.update", "tweet": { "id": "1889012345678901234", "type": "TWEET", "created_at": 1790340201000, "author": { "id": "44196397", "handle": "example" }, "subtweet": null, "reply": null, "quoted": null, "body": { "text": "Example post text", "urls": [], "mentions": [] }, "media": { "images": [], "videos": [], "thumbnails": [], "proxied": null } } } ``` - Event kinds differ by source. X: tweets (progressive mini/update/expanded/full), replies, quotes, retweets, deletions, pin/unpin, profile and follow changes. Truth Social: new truths, retruths and quotes. Instagram: posts, Stories, Reels and carousels. YouTube: uploads and Shorts, plus deletions once a video is confirmed unavailable. TikTok: uploads, reposts, live start/end and media-ready. Binance Square: posts and pin updates. News: new articles. Per-source schemas are in the documentation. ## How 1322 compares - vs the official Twitter/X API: X offers first-party pay-per-use reads and a Filtered Stream that X documents at approximately 4-5 seconds P99 latency. 1322 needs no X developer account and packages a flat tracked-account WebSocket feed instead. - vs the official Truth API (Trump Media, announced 2026-07-16): Truth API is a licensed B2B data feed for financial-services partners, live since 2026-08-01, covering posts from 10 high-profile Truth Social accounts (including @realDonaldTrump, the White House, JD Vance, Kash Patel and RFK Jr.) plus an archive back to 2022, at $60,000-$100,000/month for more than 10 customers as of 2026-08-12 (Fortune). It has no public sign-up and is not a public self-serve developer API. 1322 is unaffiliated with Trump Media and neither sells nor resells Truth API; it is self-serve, covers any tracked Truth Social account you choose, and Truth Social plans start at $300/month with WebSocket delivery a $150/month add-on — roughly 200-330x less than the reported institutional contracts. - vs scraper APIs (per-call REST scrapers): scraper APIs return data only when you poll them, so detection speed is capped by your polling interval; 1322 holds an open WebSocket and pushes each post the moment it is detected. - vs polling a profile on a timer: polling every few seconds wastes requests and adds seconds of delay; real-time push delivers as soon as the post exists. For trading, breaking-news, and prediction-market use cases where the first seconds matter, push wins. - vs single-platform tools: most alternatives cover one or two platforms; 1322 covers X, Instagram, Truth Social, YouTube, TikTok, Binance Square, and 15+ news outlets in one workspace, with a documented WebSocket contract per source. ## Frequently asked questions - Q: Is there a real-time API to track Truth Social posts? A: The official Truth API (announced by Trump Media on 2026-07-16, live to institutions since 2026-08-01) is a licensed feed covering only 10 high-profile Truth Social accounts, at a reported $60,000-$100,000/month (Fortune, 2026-08-12), with no public sign-up; there is no public self-serve developer API for arbitrary accounts. 1322 provides a managed real-time Truth Social feed for any tracked account over WebSocket (no polling), with Discord delivery included (Telegram and webhook routes depend on account configuration), from $300/month, with WebSocket delivery a $150/month add-on. Regular lanes typically run 150-250ms and the @realDonaldTrump and @WhiteHouse priority lanes around a 50ms average (observed, not an SLA). - Q: What is the best real-time Twitter/X monitoring API for tracking accounts? A: 1322 is purpose-built for tracked-account monitoring: a fixed watchlist per subscription, a WebSocket stream included on X plans, one hosted dashboard for every source, and managed Discord, Telegram and signed-webhook routes rather than ones you assemble yourself. Most alternatives are X-only data catalogs priced per call, so a watchlist that later needs Truth Social, Instagram, YouTube, TikTok, Binance Square or news means a second vendor and a second dashboard. Compare on the same accounts, region, percentiles, payloads and price. - Q: How do I monitor Instagram in real time without the official Graph API? A: The Instagram Graph API is built for account owners, not monitoring third-party accounts. 1322 monitors selected public Instagram accounts for new posts, Stories, Reels and carousels without a Graph API app, typically around a 350ms median (observed, not an SLA). Plans start at $300/month for 5 accounts with Discord delivery included; WebSocket is a $150/month add-on. - Q: What is the fastest way to get notified when a specific account posts? A: A persistent WebSocket push removes the polling interval. 1322 publishes a typical 150-250ms operating range for standard X delivery, around 100ms for selected X Ultimate accounts, and around 50ms for named Truth priority lanes. Instagram typically operates around a 350ms median. Binance Square, YouTube, TikTok and News are sub-second typical, with no published millisecond profile. All figures are observed operating figures, not an SLA. - Q: Can one product track several social platforms at once? A: Yes. 1322 manages subscriptions for X, Instagram, Truth Social, YouTube, TikTok, Binance Square, and news in one workspace. Each source is its own feed with its own WebSocket endpoint, key and documented event contract, all managed from the same dashboard. - Q: Can 1322 monitor TikTok creators in real time? A: Yes. Add creator accounts by username or sec_uid to a private watchlist and receive uploads, reposts, live starts, live ends, and a media-ready event over REST, WebSocket, and the Discord bot. No TikTok developer account is required. TikTok plans start at $200/month for 5 tracked creators. - Q: How do I get notified when a TikTok creator goes live? A: Add the creator to a tracked list by @username and 1322 pushes a tiktok.live.started event as the session opens, typically sub-second, to the included Discord bot or your own WebSocket consumer. No official TikTok developer surface exposes a live-start subscription for a creator you do not control, because each one is scoped to a creator who has connected their own account to your app. tiktok.live.ended is a separate event carrying the same room_id as the start, so a bot can open one alert and later close that same alert instead of leaving a stale "LIVE NOW" card. Plans start at $200/month for 5 tracked creators. - Q: Is there a free option? A: Self-hosted open-source collectors can be free to run but you maintain them. 1322 base plans are sold per source, starting at $150/month for YouTube and $250/month for X; WebSocket is included for X and is an add-on for other sources. Open example clients are on GitHub. ## Contact - [Discord](https://discord.gg/1322) - [Email support](mailto:support@1322.io) --- # Per-platform API reference ## X / Twitter (platform id: x) Twitter/X tracking, real-time events, and managed accounts via api.1322.io and the ws.normal / ws.ultimate WebSocket endpoints. - REST base: https://api.1322.io - WebSocket: wss://ws.normal.1322.io/ws/normal — Normal tier. Tweet events + profile events + following events. - WebSocket: wss://ws.ultimate.1322.io/ws/ultimate — Ultimate tier. Tweet events (profile/following events may only arrive on normal). Hybrid accounts should connect to both endpoints simultaneously and dedupe by tweet.id. - Authentication: REST: send the API key via query key=, header X-API-Key, or Authorization: Bearer . WebSocket: same headers, or query token=. Use the key that matches the stream (normal key for the normal URL, ultimate key for the 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. ### X / Twitter management endpoints #### GET /v1/tracked Retrieve all Twitter accounts you are currently tracking. (authentication required) Response example: ``` { "success": true, "tier": "normal", "page": 1, "trackedAccounts": [ { "createdAt": "2025-02-13T12:00:00Z", "twitterId": "44196397", "twitterUsername": "elonmusk" } ] } ``` #### GET /v1/keys Returns all keys associated with your account. Essential for hybrid subscriptions to discover both Normal and Ultimate keys. (authentication required) Response example: ``` { "plan": "hybrid", "keys": [ { "tier": "normal", "key": "9121dc75-...", "trackedCount": 800, "totalLimit": 1500 }, { "tier": "ultimate", "key": "a1b2c3d4-...", "trackedCount": 0, "totalLimit": 50 } ] } ``` #### POST /v1/tracked Add one or more Twitter accounts. Send multiple accounts as a comma-separated list. Usernames and IDs are resolved automatically. (authentication required) Request example: ``` curl -X POST "https://api.1322.io/v1/tracked" \ -H "Content-Type: application/json" \ -H "X-API-Key: YOUR_API_KEY_HERE" \ -d '{"identifiers": "elonmusk,@twitter,44196397", "type": "username"}' ``` Response example: ``` { "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": [] } } ``` #### DELETE /v1/tracked Remove one or more Twitter accounts from your tracking list. (authentication required) Request example: ``` curl -X DELETE "https://api.1322.io/v1/tracked" \ -H "Content-Type: application/json" \ -H "X-API-Key: YOUR_API_KEY_HERE" \ -d '{"identifiers": "elonmusk,@twitter", "type": "username"}' ``` Response example: ``` { "success": true, "message": "processed identifiers", "tier": "normal", "results": { "successful": [{ "identifier": "elonmusk,@twitter" }], "skipped": [], "failed": [] } } ``` #### GET /v1/data/tweet/:id Fetch any tweet by its snowflake ID. Use the full or expanded boolean query parameters to request untruncated text. Returns the full TwitterTweet object. (authentication required) Request example: ``` curl "https://api.1322.io/v1/data/tweet/1234567890123456789?full=true" \ -H "X-API-Key: YOUR_API_KEY_HERE" ``` Response example: ``` { "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 } } } ``` #### GET /v1/resolve/username/:username Resolve an X username to a Twitter ID. Returns the user's ID, display name, follower count, and account status. (authentication required) Request example: ``` curl "https://api.1322.io/v1/resolve/username/elonmusk" \ -H "X-API-Key: YOUR_API_KEY_HERE" ``` Response example: ``` { "username": "elonmusk", "twitterId": "44196397", "displayName": "Elon Musk", "followers": 210000000, "status": "active" } ``` #### GET /v1/health Returns the health status of the API. No authentication required. (no authentication) Response example: ``` { "status": "ok" } ``` ### X / Twitter WebSocket event types #### tweet.mini.update The main event for tweets — this is the first event for ANY tweet. Brief information for speed. If the tweet is a quote/retweet/etc it won't yet contain subtweet information. ```ts export interface MiniTweetUpdate { type: 'tweet.mini.update'; tweet: TwitterMiniTweet; } ``` #### tweet.update Full information on a tweet. Sent shortly after tweet.mini.update if the tweet is a quote, reply, retweet, or contains a URL with a card. ```ts export interface TweetUpdate { type: 'tweet.update'; tweet: TwitterTweet; } ``` #### tweet.update.expanded Includes the FULL text of any tweet (tweet.update truncates it) and info about articles. Only sent if there's an article or truncated text. ```ts export interface TweetUpdateExpanded { type: 'tweet.update.expanded'; tweet: TwitterTweet; } ``` #### tweet.deleted ```ts export interface DeletedTweet { type: 'tweet.deleted'; tweet: TwitterTweet; // metrics may be outdated (likes, replies, retweets, etc) deleted_at: number; } ``` #### tweet.full Fullchain — the 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. ```ts export interface TweetFull { type: 'tweet.full'; tweet: TwitterTweet; // Fullchain: subtweet forms a recursive chain of full tweets } ``` #### profile.update ```ts export interface ProfileUpdate { type: 'profile.update'; user: TwitterUser; // The new profile information for this user before: TwitterUser; // The old profile information for this user } ``` #### following.update ```ts 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 } ``` #### profile.pinned.update / profile.unpinned.update ```ts 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; pinned: TwitterTweet[]; } ``` ### X / Twitter type definitions #### WebsocketWorkerEvent (base message) ```ts export interface WebsocketWorkerEvent { id: string; // Unique ID for this event (usable for debouncing/dedup across connections) type: string; // The type of event being sent source: "1322"; // Always "1322", identifies the event origin } ``` #### TwitterUser (full profile) ```ts export interface TwitterUser { id: string; handle: string; private: boolean; verified: boolean | VerificationBadge; sensitive: boolean; restricted: boolean; joined_at: number; // UNIX ms profile: { name: string; location: null | string; avatar: null | string; banner: null | string; pinned: string[]; url: null | { name: string; url: string; tco: string }; description: { text: string; urls: { name: string; url: string; tco: string }[] }; }; metrics: { likes: number; media: number; tweets: number; friends: number; followers: number; following: number }; } ``` #### VerificationBadge ```ts interface VerificationBadge { type: 'none' | 'blue' | 'gold'; // none=unverified, blue=standard checkmark, gold=organization label: null | { description: string; badge: string | null; url: string | null }; } // Treat verified: true or type !== 'none' as having a checkmark. Use label only for org-linked badges. ``` #### TwitterMiniUser ```ts interface TwitterMiniUser { id: string; handle: string; name?: string; avatar?: string; verified?: boolean | VerificationBadge; profile?: { name: string; avatar: string | null }; metrics?: { following: number; followers: number }; } ``` #### TwitterMiniTweet ```ts export interface TwitterMiniTweet { id: string; type: 'TWEET' | 'RETWEET' | 'QUOTE' | 'REPLY'; created_at: number; // UNIX ms author: TwitterMiniUser; subtweet: null | TwitterMiniTweet; reply: null | { id: string; handle: string }; quoted: null | { id: string; handle: string }; body: { text: string; urls: { name: string; url: string; tco: string }[]; mentions: { id: string; name: string; handle: string }[]; }; media: { images: string[]; videos: string[]; thumbnails: string[]; proxied: null | { images: string[] }; // fall back to normal media URLs if unavailable }; } ``` #### TwitterTweet (full) ```ts export interface TwitterTweet { id: string; type: 'TWEET' | 'RETWEET' | 'QUOTE' | 'REPLY'; created_at: number; // UNIX ms author: TwitterUser; subtweet: null | TwitterTweet; reply: null | { id: string; handle: string }; quoted: null | { id: string; handle: string }; body: { text: string; urls: { name: string; url: string; tco: string }[]; mentions: { id: string; name: string; handle: string }[]; components: ( | { type: 'text'; text: string; bold: boolean; italics: boolean } | { type: 'image'; url: string } | { type: 'video'; url: string } )[]; }; media: { images: string[]; videos: string[]; thumbnails: string[]; proxied: null | { images: string[]; thumbnails: string[] }; }; grok: null | { id: string; conversation: { from: 'USER' | 'AGENT'; message: string; images: string[] }[] }; card: null | { url: string; image: string; title: string; description: string }; poll: null | { ends_at: number; updated_at: number; choices: { label: string; count: number }[] }; article: null | { id: string; title: string; thumbnail: null | string; created_at: number; updated_at: number; body: { text: string; components: ( | { type: 'divider' } | { type: 'text'; variant: 'header-one' | 'header-two' | 'paragraph' | 'blockquote' | 'ordered-list' | 'unordered-list' | 'latex-box' | 'markdown-box'; lines: { text: string; styles: { from: number; to: number; text: 'bold' | 'italics' | 'strikethrough' }[]; urls: { from: number; to: number; url: string }[] }[] } | { type: 'media'; variant: 'image' | 'gif' | 'video'; url: string; thumbnail: string; caption: null | string } | { type: 'tweet'; tweet: { id: string; url: string; object: null | TwitterTweet } } )[]; }; }; metrics: { likes: number; quotes: number; replies: number; retweets: number; advanced: null | { views: number }; // null until fetched with the expanded variant }; community?: { id: string; name: string; url: string }; // present when fetched with ?full=true } ``` ### X / Twitter notes - Connection: server -> client sends text frames only, one JSON object per frame (UTF-8). One-way for events — you only need to handle incoming messages. Server sends periodic pings; respond with pongs. - Filtered stream: you only receive events for Twitter user IDs in your tracked list for the key you used. Manage tracked accounts via the REST API; the stream updates automatically. - Event flow for tweets: they arrive progressively across stages, each enriches the previous — tweet.mini.update (fastest) -> tweet.update (enrichment) -> tweet.update.expanded (untruncated text/articles) -> tweet.full (fullchain). - Additive merge (recommended): merge stages by tweet.id (snowflake). Use the longest body.text, union all media arrays, keep the deepest subtweet chain, take the highest metric values, and never overwrite a populated field with null/empty — a later stage may lack data an earlier stage had. - Hybrid clients (both normal + ultimate keys) should connect to both endpoints simultaneously and dedupe by tweet.id across both streams, merging stages additively. - 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. - Call the API from your own server, never from browser code: your API key must stay private, and the REST endpoints are not built for cross-origin (CORS) browser requests. ## Truth Social (platform id: truth-social) Direct monitoring of Truth Social posts, retruths, quotes, and media streams via truth.1322.io. - REST base: https://truth.1322.io - WebSocket: wss://truth.1322.io/{path}?key={ws_key} — Path and WS key are provided in your dashboard configuration. - Authentication: All endpoints except /health require the X-Api-Key header with your API key. WebSocket: connect with your WS key via the key= query parameter. - Rate limit: Rate limits are per-key and shown in the /v1/limits response. Standard HTTP status codes (401, 403, 429) are used for errors. ### Truth Social management endpoints #### GET /health Returns the health status of the API. No authentication required. (no authentication) Request example: ``` curl "https://truth.1322.io/health" ``` Response example: ``` { "status": "ok" } ``` #### GET /v1/status Returns the current service status including post processing counts and error totals. (authentication required) Request example: ``` curl "https://truth.1322.io/v1/status" \ -H "X-Api-Key: YOUR_API_KEY_HERE" ``` Response example: ``` { "posts_processed": 1234, "errors_total": 0, "status": "running" } ``` #### GET /v1/list List all Truth Social accounts currently being tracked for your server. (authentication required) Request example: ``` curl "https://truth.1322.io/v1/list" \ -H "X-Api-Key: YOUR_API_KEY_HERE" ``` Response example: ``` [ { "handle": "realDonaldTrump", "display_name": "Donald J. Trump", "added_by": "admin", "added_at": "2025-06-15T08:30:00Z" }, { "handle": "DanScavino", "display_name": "Dan Scavino", "added_by": "admin", "added_at": "2025-06-15T09:00:00Z" } ] ``` #### GET /v1/limits Returns your current tracking usage, maximum limits, and rate limits. (authentication required) Request example: ``` curl "https://truth.1322.io/v1/limits" \ -H "X-Api-Key: YOUR_API_KEY_HERE" ``` Response example: ``` { "current_tracked": 3, "max_tracked": 5, "rpm": 60, "tracked": ["danscavino", "elonmusk", "realdonaldtrump"] } ``` #### POST /v1/track Add a Truth Social account to your tracking list. Send the handle in the JSON body. (authentication required) Request example: ``` curl -X POST "https://truth.1322.io/v1/track" \ -H "Content-Type: application/json" \ -H "X-Api-Key: YOUR_API_KEY_HERE" \ -d '{"handle": "realDonaldTrump"}' ``` Response example: ``` { "status": "ok", "account": "realDonaldTrump", "uid": "107780257626128497", "display_name": "Donald J. Trump", "tracked": ["danscavino", "elonmusk", "realdonaldtrump"], "current_tracked": 3, "max_tracked": 5 } ``` #### POST /v1/untrack Remove a Truth Social account from your tracking list. Send the handle in the JSON body. (authentication required) Request example: ``` curl -X POST "https://truth.1322.io/v1/untrack" \ -H "Content-Type: application/json" \ -H "X-Api-Key: YOUR_API_KEY_HERE" \ -d '{"handle": "realDonaldTrump"}' ``` Response example: ``` { "status": "ok", "account": "realDonaldTrump", "tracked": ["danscavino", "elonmusk"], "current_tracked": 2, "max_tracked": 5 } ``` ### Truth Social WebSocket event types #### post (unnamed event — every WS message is a TruthSocialPost) quoted / quoted.quoted support two levels of quote resolution. is_retruth / retruth_of_id marks a retruth (boost). Author avatar URLs are pre-proxied — use them directly in . retruth_of, quoted.author, quoted.quoted.author are additive optional fields; existing clients are unaffected. ```ts export interface TruthSocialPost { platform: 'truth'; username: string; // on retruths/quotes this is the outer actor display_name: string; user_avatar: string; user_following: number; user_followers: number; user_id: string; key: string; // unique post ID (Mastodon-style snowflake) — use for dedup timestamp: string; seen_at: string; // ISO-8601, when 1322 first detected the post text: string; is_quote?: boolean; quoted?: { key: string; text: string; url?: string; author?: TruthSocialAuthor; // original author of the quoted post quoted?: { key: string; text: string; url?: string; author?: TruthSocialAuthor }; // nested quote-of-a-quote }; is_retruth?: boolean; retruth_of_id?: string; retruth_of?: TruthSocialAuthor; // original author of the retruthed post card?: { url: string; title?: string; description?: string; image?: string }; media?: TruthSocialMediaAttachment[]; } ``` ### Truth Social type definitions #### TruthSocialMediaAttachment ```ts export interface TruthSocialMediaAttachment { kind: 'image' | 'video' | 'gifv' | 'audio' | string; url: string; poster_url: string; created_at: string; source?: 'own' | 'quoted' | 'nested_quoted'; } // source: "own" = attached directly to this post, "quoted" = from the quoted post, // "nested_quoted" = from a quote-of-a-quote (the inner quoted post). ``` #### TruthSocialAuthor ```ts export interface TruthSocialAuthor { id?: string; // original user_id, useful for dedupe username: string; // handle (e.g. "realDonaldTrump") display_name?: string; avatar?: string; // proxied avatar URL (same proxy as user_avatar) } ``` ### Truth Social notes - The docs page does not distinguish separate WS event 'type' fields for Truth Social the way X does — every WebSocket message is a TruthSocialPost object; is_quote/is_retruth flags indicate the post's relationship to other posts. - Call the API from your own server, never from browser code: your API key must stay private, and the REST endpoints are not built for cross-origin (CORS) browser requests. ## Instagram (platform id: instagram) Monitor Instagram posts, reels, stories, and carousels in real time via 1322.io (v2 API). - REST base: https://1322.io - WebSocket: wss://1322.io/IG?key={api_key} — Authenticate with ?key= on the connection URL. - Authentication: Send the API key via header Authorization: Bearer or X-API-Key: . All endpoints, including /v1/health, require authentication. - Rate limit: Per-key RPM limit returned in the /v1/limits response. Standard HTTP status codes (401, 403, 429) are used for errors. ### Instagram management endpoints #### GET /v1/health Returns the health status of the API. (authentication required) Request example: ``` curl "https://1322.io/v1/health" \ -H "X-API-Key: YOUR_API_KEY_HERE" ``` Response example: ``` { "ok": true } ``` #### GET /v1/limits Returns your current tracking usage, maximum limits, and request rate limits. (authentication required) Request example: ``` curl "https://1322.io/v1/limits" \ -H "X-API-Key: YOUR_API_KEY_HERE" ``` Response example: ``` { "status": "success", "max_tracked": 10, "current": 3, "rpm": 60 } ``` #### GET /v1/list List all Instagram accounts currently being tracked under your subscription. (authentication required) Request example: ``` curl "https://1322.io/v1/list" \ -H "X-API-Key: YOUR_API_KEY_HERE" ``` Response example: ``` { "status": "success", "tracked": ["elonmusk", "nike", "natgeo"], "current": 3, "max_tracked": 10 } ``` #### POST /v1/track Add an Instagram account to tracking. Verifies the account exists before adding. (authentication required) Request example: ``` curl -X POST "https://1322.io/v1/track" \ -H "Content-Type: application/json" \ -H "X-API-Key: YOUR_API_KEY_HERE" \ -d '{"username": "instagram"}' ``` Response example: ``` { "status": "success", "message": "Now tracking instagram", "tracked": ["elonmusk", "nike", "natgeo", "instagram"], "current": 4, "max_tracked": 10 } ``` #### POST /v1/untrack Remove an Instagram account from your tracking list. Send the username in the JSON body. (authentication required) Request example: ``` curl -X POST "https://1322.io/v1/untrack" \ -H "Content-Type: application/json" \ -H "X-API-Key: YOUR_API_KEY_HERE" \ -d '{"username": "elonmusk"}' ``` Response example: ``` { "status": "success", "message": "Stopped tracking elonmusk", "tracked": ["nike", "natgeo"], "current": 2, "max_tracked": 10 } ``` ### Instagram WebSocket event types #### post (unnamed event — every WS message is an InstagramPost) is_collab/collab_with, is_pinned, is_paid_partnership, and location are additive optional fields; existing clients are unaffected. ```ts export interface InstagramPost { platform: 'instagram'; username: string; display_name: string; user_avatar: string; user_followers: number; user_id: string; key: string; // post id timestamp: string; seen_at: string; text: string; post_type: 'post' | 'reel' | 'story' | 'carousel'; media_count?: number; hashtags?: string[]; mentions?: string[]; // includes coauthor usernames even when not @-mentioned media?: InstagramMediaAttachment[]; is_collab?: boolean; // coauthor present, or owner != tracked account collab_with?: string[]; // other accounts on the collab (excludes tracked) is_pinned?: boolean; // pinned to the tracked account's profile is_paid_partnership?: boolean; // paid / branded-content flag from IG location?: { name: string; lat?: number; lng?: number }; // place tag, when present } ``` ### Instagram type definitions #### InstagramMediaAttachment ```ts export interface InstagramMediaAttachment { // Backward-compatible type: video COVER frames stay 'image' here so existing clients keep working. kind: 'image' | 'video'; // Precise type + recommended discriminator (use media_role): kind_v2?: 'image' | 'video_cover' | 'video'; media_role?: 'image' | 'video_cover' | 'video'; is_video_cover?: boolean; // true only for a video's preview/cover frame media_index: number; // index within media[] carousel_index?: number; // original IG carousel index (video + its cover share it) video_index?: number; // ordinal among video items cover_media_index?: number; // on a video: matching cover item in media[] cover_url?: string; // on a video: URL of the matching cover image covers_video_media_index?: number; // on a cover: matching video item in media[] covers_video_url?: string; // on a cover: URL of the matching video file url: string; // CDN/proxy URL (images via wsrv.nl; video via igmedia.1322.io) width?: number; height?: number; created_at: string; // ISO-8601 UTC } ``` ### Instagram notes - Error codes on POST /v1/track: list_full (tracking list at capacity), already_tracked, invalid_user, storage_error. - Call the API from your own server, never from browser code: your API key must stay private, and the REST endpoints are not built for cross-origin (CORS) browser requests. ## YouTube (platform id: youtube) Real-time tracking of YouTube channels via youtube.1322.io. Manage tracked channels over REST, then consume upload, upgrade and deletion messages over WebSocket. Channels accept a UC-prefixed channel ID, an @handle, or a channel URL. - REST base: https://youtube.1322.io - WebSocket: wss://youtube.1322.io/{ws_path}?key={ws_key} — GET /v1/dashboard returns a complete ws_url plus ws_key (also shown on your dashboard API Access page) — no path assembly is needed. The stream accepts the WS key EITHER as the key= query parameter on that URL OR as the X-WS-KEY header. Use one, not both. Each inbound message is one UTF-8 JSON object per text frame. The server pings every 30 seconds and most WebSocket libraries answer automatically; reconnect with capped exponential backoff. Events are NOT replayed while a client is offline, so anything published during a disconnect is missed. - Authentication: REST accepts EITHER `Authorization: Bearer ` OR `X-Api-Key: ` on every endpoint — the two are interchangeable. WebSocket accepts EITHER `?key=` on the ws_url from /v1/dashboard OR the `X-WS-KEY` header. - Rate limit: Per-key RPM limits apply (see GET /v1/limits). Standard HTTP status codes (401, 403, 429) are used for errors. ### YouTube management endpoints #### GET /v1/status Returns tracker health rather than account state: status, posts_processed, errors_total, and a feed_errors object holding a per-feed-provider error breakdown. Use GET /v1/dashboard for plan, term and tracked list. (authentication required) Request example: ``` curl "https://youtube.1322.io/v1/status" \ -H "X-Api-Key: YOUR_API_KEY_HERE" ``` Response example: ``` { "status": "ok", "posts_processed": 1284, "errors_total": 3, "feed_errors": { } } ``` #### GET /v1/dashboard Returns account status, term, slot usage, the channels you currently track, and your WebSocket URL + key. The response is FLAT — every field sits at the top level and the tracked list is `tracked`. YouTube returns a complete ws_url here, unlike TikTok's nested websocket.path. YouTube lists tracked channels here and on GET /v1/list; there is no /v1/tracked endpoint. (authentication required) Request example: ``` curl "https://youtube.1322.io/v1/dashboard" \ -H "X-Api-Key: YOUR_API_KEY_HERE" ``` Response example: ``` { "server_id": "yt_xxxxxxxx", "status": "active", "is_lifetime": false, "expires_at": "2026-09-20T00:00:00Z", "days_remaining": 26, "max_tracked": 50, "current": 1, "current_tracked": 1, "remaining_slots": 49, "rpm": 60, "ws_enabled": true, "ws_url": "wss://youtube.1322.io/yt_xxxxxxxx", "ws_key": "your_ws_key", "discord_enabled": false, "tracked": [ { "channel_id": "UCX6OQ3DkcsbYNE6H8uQQuVA", "name": "MrBeast", "added_at": "2026-08-01T09:14:00Z" } ] } ``` #### GET /v1/list Returns the tracked YouTube channels on their own, as the same channel_id / name / added_at rows that GET /v1/dashboard embeds under `tracked`. Use it when you want the watchlist without the account and WebSocket fields. (authentication required) Request example: ``` curl "https://youtube.1322.io/v1/list" \ -H "X-Api-Key: YOUR_API_KEY_HERE" ``` #### GET /v1/limits Returns current tracking usage, maximum limit, and rate limit. (authentication required) Request example: ``` curl "https://youtube.1322.io/v1/limits" \ -H "X-Api-Key: YOUR_API_KEY_HERE" ``` Response example: ``` { "current_tracked": 1, "max_tracked": 50, "rpm": 60 } ``` #### POST /v1/track Add a YouTube channel to your tracking list. Send channel in the JSON body — a UC-prefixed channel ID, an @handle, or a channel URL (all resolve to the same channel). (authentication required) Request example: ``` curl -X POST "https://youtube.1322.io/v1/track" \ -H "Content-Type: application/json" \ -H "X-Api-Key: YOUR_API_KEY_HERE" \ -d '{"channel": "@MrBeast"}' ``` Response example: ``` { "status": "ok", "channel_id": "UCX6OQ3DkcsbYNE6H8uQQuVA", "tracked": ["UCX6OQ3DkcsbYNE6H8uQQuVA"], "max_tracked": 50 } ``` #### POST /v1/untrack Remove a YouTube channel from your tracking list. Send channel in the JSON body (UC id, @handle, or URL). (authentication required) Request example: ``` curl -X POST "https://youtube.1322.io/v1/untrack" \ -H "Content-Type: application/json" \ -H "X-Api-Key: YOUR_API_KEY_HERE" \ -d '{"channel": "UCX6OQ3DkcsbYNE6H8uQQuVA"}' ``` Response example: ``` { "status": "ok", "channel_id": "UCX6OQ3DkcsbYNE6H8uQQuVA", "tracked": [], "max_tracked": 50 } ``` #### GET /v1/ws/status Reports the state of your stream — whether WebSocket delivery is enabled on your account and how it is currently being used. This is a REST call, so it authenticates with the API key; the connection details themselves (ws_url, ws_key) come from GET /v1/dashboard. (authentication required) Request example: ``` curl "https://youtube.1322.io/v1/ws/status" \ -H "X-Api-Key: YOUR_API_KEY_HERE" ``` #### GET /v1/health Liveness check. Point uptime monitors and load-balancer probes here rather than polling an authenticated endpoint on a timer. (no authentication) Request example: ``` curl "https://youtube.1322.io/v1/health" ``` #### GET /v1/docs The tracker's own human-readable API reference. (no authentication) Request example: ``` curl "https://youtube.1322.io/v1/docs" ``` #### GET /openapi.json Machine-readable OpenAPI description of the tracker API, for generating a client. (no authentication) Request example: ``` curl "https://youtube.1322.io/openapi.json" ``` ### YouTube WebSocket event types #### upload PRIMARY event — sent for every detected video, and the only one you can rely on arriving. Carries the channel, the video, and the images resolvable at detection time; images.chosen is the best available then. subtype separates a video from a short. ```ts export interface UploadMessage { type: "upload"; subtype: "video" | "short"; detected_at: string; channel: { id: string | null; name: string | null; url: string | null; avatar: string | null }; video: { id: string; url: string; title: string | null; description: string | null; published_at: string | null; updated_at: string | null; view_count?: number; duration_display?: string; metadata?: Record; }; images: { seed: string | null; chosen: string | null; thumbnail_small: string | null }; } ``` #### upgrade CONDITIONAL — sent only when a later thumbnail retry improves an image that was still unconfirmed at upload time. Most videos never produce one, so nothing should wait for it. When it arrives, match upgrade.video_id to an upload you already rendered and swap the image. ```ts export interface UpgradeMessage { type: "upgrade"; detected_at: string; upgrade: { kind: "image"; video_id: string; url: string }; // replacement image } ``` #### deletion INDEPENDENT — emitted once a previously detected video is explicitly confirmed unavailable. It is not the closing step of a per-video sequence and may follow an upload after any interval, or never. ```ts export interface DeletionMessage { type: "deletion"; detected_at: string; video: { id: string; url: string }; // the deleted video's ID and original URL channel: { id: string | null; name: string | null; url: string | null; avatar: string | null }; } ``` ### YouTube type definitions #### YouTubeTrackerMessage (union) ```ts export type YouTubeTrackerMessage = UploadMessage | UpgradeMessage | DeletionMessage; ``` ### YouTube notes - The three message types are NOT a guaranteed three-message sequence per video. "upload" is the primary event; "upgrade" is conditional, sent only when a later thumbnail retry improves an initially unconfirmed image; "deletion" is an independent later event after the video is explicitly confirmed unavailable. Build the consumer around "upload" alone — a video that receives neither an upgrade nor a deletion is the normal case. - Auth accepts two forms on each side. REST: `Authorization: Bearer ` or `X-Api-Key: `. WebSocket: `?key=` on the ws_url, or the `X-WS-KEY` header. - GET /v1/dashboard is FLAT: server_id, status, is_lifetime, expires_at, days_remaining, max_tracked, current, current_tracked, remaining_slots, rpm, ws_enabled, ws_url, ws_key, discord_enabled, tracked[{channel_id, name, added_at}]. It supplies a complete ws_url, so no path assembly is needed. - GET /v1/status is tracker health, not account state: status, posts_processed, errors_total, and a per-feed-provider feed_errors breakdown. - YouTube tracks channels. Channels accept a UC-prefixed channel ID, an @handle, or a channel URL — all three resolve to the same channel. - Call the API from your own server, never from browser code: your API key must stay private, and the REST endpoints are not built for cross-origin (CORS) browser requests. ## TikTok (platform id: tiktok) Real-time monitoring of TikTok creator accounts via tiktok.1322.io. Creators are tracked by username or sec_uid over REST; uploads (video, photo and carousel posts), reposts, live starts, live ends, and media-ready frames are delivered over WebSocket. Clients linked to a Discord server also get Discord bot delivery; clients without one use the API and WebSocket only. - REST base: https://tiktok.1322.io - WebSocket: wss://tiktok.1322.io{ws_path} — ws_path is opaque and account-specific — a /ws/<32-hex> value. Read it from GET /v1/ws/status (field: path) or GET /v1/dashboard (field: websocket.path). There is no flat ws_url on the dashboard response. There is NO query string: authenticate with a header (X-WS-Key or Authorization: Bearer), never by appending a key to the URL — query-string keys are not enabled. Handshake failures return before the upgrade: 401 wrong or missing key, 403 expired tenant / WebSocket disabled / origin denied, 404 wrong path, 429 connection limit reached. A successful handshake is 101. Limits: 16 concurrent connections per account, 8 per IP. - Authentication: TikTok issues TWO separate keys: REST uses your API key, the WebSocket uses a separate WebSocket key. Do NOT mix them. REST (every endpoint except the public health and readiness probes and the signed media download) accepts EITHER `X-API-Key: ` OR `Authorization: Bearer `. WebSocket accepts EITHER `X-WS-Key: ` OR `Authorization: Bearer `. Mixing is rejected — the api_key sent as X-WS-Key returns 401. Query-string keys are not enabled on either side. - Rate limit: Per-key rate limits apply. Standard HTTP status codes (401, 403, 429) are used for errors. WebSocket ceilings are returned by GET /v1/limits (ws_max_connections 16, ws_max_connections_per_ip 8). ### TikTok management endpoints #### GET /v1/status Returns your client record: status, tracked count against your maximum, and which delivery channels are enabled. client.expires_at is an RFC3339 timestamp present once a term has been set; it is ABSENT (not null) on a client with no term yet, which is a real state rather than a missing feature. (authentication required) Request example: ``` curl "https://tiktok.1322.io/v1/status" \ -H "X-API-Key: YOUR_API_KEY_HERE" ``` Response example: ``` { "client": { "client_id": "tt_1a2b3c4d", "name": "Example Desk", "status": "active", "expires_at": "2026-09-20T00:00:00Z", "max_accounts": 60, "tracked_count": 2, "api_enabled": true, "websocket_enabled": true, "discord_enabled": false }, "ready": true } ``` #### GET /v1/dashboard Returns everything in one call: client record, limits, tracked creators, and the WebSocket path. The response is NESTED — there is no flat tenant_id, expires_at or ws_url at the top level, and the tracked list is `tracks`, not `tracked`. Reading it flat yields undefined everywhere. (authentication required) Request example: ``` curl "https://tiktok.1322.io/v1/dashboard" \ -H "X-API-Key: YOUR_API_KEY_HERE" ``` Response example: ``` { "client": { "client_id": "tt_1a2b3c4d", "name": "Example Desk", "status": "active", "expires_at": "2026-09-20T00:00:00Z", "max_accounts": 60, "tracked_count": 2, "api_enabled": true, "websocket_enabled": true, "discord_enabled": false }, "limits": { "accounts": { "maximum": 60, "current": 2, "remaining": 58 }, "ws_max_connections_per_ip": 8, "ws_max_connections": 16 }, "tracks": [ { "track_id": "trk_8f21", "username": "examplecreator", "sec_uid": "MS4wLjABAAAA...", "events": ["upload", "repost", "live"], "state": "active", "ws_delivery": true, "discord_delivery": false } ], "websocket": { "enabled": true, "path": "/ws/3f9c1d7e5a2b48c6910d4e7f2a6b8c31", "current_connections": 0, "unique_ips": 0, "max_connections": 16, "max_per_ip": 8 } } ``` #### GET /v1/list Lists every TikTok creator currently tracked on your account, with the event types and delivery routes enabled for each. To look up one creator, call GET /v1/list and match on track_id. (authentication required) Request example: ``` curl "https://tiktok.1322.io/v1/list" \ -H "X-API-Key: YOUR_API_KEY_HERE" ``` Response example: ``` { "tracks": [ { "track_id": "trk_8f21", "username": "examplecreator", "sec_uid": "MS4wLjABAAAA...", "events": ["upload", "repost", "live"], "state": "active", "ws_delivery": true, "discord_delivery": false }, { "track_id": "trk_44c0", "username": "anothercreator", "sec_uid": "MS4wLjABAAAB...", "events": ["upload"], "state": "active", "ws_delivery": true, "discord_delivery": false } ], "count": 2 } ``` #### GET /v1/limits Returns creator slot usage and the WebSocket connection ceilings. (authentication required) Request example: ``` curl "https://tiktok.1322.io/v1/limits" \ -H "X-API-Key: YOUR_API_KEY_HERE" ``` Response example: ``` { "accounts": { "maximum": 60, "current": 2, "remaining": 58 }, "ws_max_connections_per_ip": 8, "ws_max_connections": 16 } ``` #### POST /v1/track Add a TikTok creator to your tracking list. Send username or sec_uid in the JSON body. (authentication required) Request example: ``` curl -X POST "https://tiktok.1322.io/v1/track" \ -H "Content-Type: application/json" \ -H "X-API-Key: YOUR_API_KEY_HERE" \ -d '{"username": "examplecreator"}' ``` Response example: ``` { "status": "ok", "message": "Now tracking examplecreator", "track_id": "trk_8f21", "username": "examplecreator", "sec_uid": "MS4wLjABAAAA...", "tracked": ["examplecreator", "anothercreator"], "current": 2, "max_accounts": 60 } ``` #### POST /v1/untrack Remove a TikTok creator from your tracking list. Send username, sec_uid, or track_id in the JSON body. (authentication required) Request example: ``` curl -X POST "https://tiktok.1322.io/v1/untrack" \ -H "Content-Type: application/json" \ -H "X-API-Key: YOUR_API_KEY_HERE" \ -d '{"username": "examplecreator"}' ``` Response example: ``` { "status": "ok", "message": "Stopped tracking examplecreator", "track_id": "trk_8f21", "username": "examplecreator", "current": 1, "max_accounts": 60 } ``` #### GET /v1/ws/status Returns whether the stream is enabled, the opaque connection path, and current connection usage against your ceiling. This is a REST call, so it authenticates with the API key; the stream itself authenticates with the separate WebSocket credential. (authentication required) Request example: ``` curl "https://tiktok.1322.io/v1/ws/status" \ -H "X-API-Key: YOUR_API_KEY_HERE" ``` Response example: ``` { "enabled": true, "path": "/ws/3f9c1d7e5a2b48c6910d4e7f2a6b8c31", "current_connections": 0, "unique_ips": 0, "max_connections": 16, "max_per_ip": 8 } ``` #### GET /v1/media/{video_id}.mp4 Download the file from object.media_url on the tiktok.media.ready frame. The URL is short-lived and signed (exp and sig query parameters); no API key is needed, and a bare /v1/media/{video_id}.mp4 without its signature returns 403. A 503 with Retry-After: 1 means the file is not ready yet. Returns the media file, not JSON. (no authentication) Request example: ``` curl -o video.mp4 "$MEDIA_URL" # object.media_url from tiktok.media.ready ``` #### GET /health Liveness check. No authentication required. (no authentication) Request example: ``` curl "https://tiktok.1322.io/health" ``` #### GET /healthz Liveness check. No authentication required. (no authentication) Request example: ``` curl "https://tiktok.1322.io/healthz" ``` #### GET /readyz Readiness check. No authentication required. (no authentication) Request example: ``` curl "https://tiktok.1322.io/readyz" ``` #### GET /v1/health Tenant health on the versioned surface. Requires the API key. (authentication required) Request example: ``` curl "https://tiktok.1322.io/v1/health" \ -H "X-API-Key: YOUR_API_KEY_HERE" ``` ### TikTok WebSocket event types #### tiktok.upload.created The tracked creator posted new content. object.kind ("video" | "photo" | "carousel") tells you which without inspecting media; a photo post or carousel carries object.image_urls (string[]) instead of a video. object.mentions and object.hashtags are parsed from the description (hashtags without the leading #, mentions without the leading @). object.duration is seconds, object.music describes the attached sound, and object.title carries a post title where TikTok supplies one separately from description. occurred_at is set on uploads. ```ts // Content events use schema "1322.tiktok.event.v1". Branch on type. { "schema": "1322.tiktok.event.v1", "event_id": "01J9Z8QX4T7C2V1M0K3R5B6N7P", "type": "tiktok.upload.created", "platform": "tiktok", "account": { "username": "examplecreator", "display_name": "Example Creator", "sec_uid": "MS4wLjABAAAA...", "verified": true }, "object": { "video_id": "7300000000000000000", "url": "https://www.tiktok.com/@examplecreator/video/7300000000000000000", "kind": "video", "title": "new video", "description": "new video @friendcreator #launch #demo", "cover_url": "https://.../cover.jpg", "mentions": ["friendcreator"], "hashtags": ["launch", "demo"], "duration": 27, "music": { "title": "original sound - examplecreator", "author_name": "Example Creator", "original": true, "duration": 27 } }, "occurred_at": "2026-08-22T14:03:11Z", "observed_at": "2026-08-22T14:03:12Z", "delivery": { "mode": "live_only" } } ``` #### tiktok.repost.created The tracked creator reposted another creator's video. Read original_author.username — printing original_author directly renders "[object Object]". occurred_at is null on reposts. ```ts // object.original_author is an OBJECT describing the creator whose video was reposted. { "type": "tiktok.repost.created", "object": { "video_id": "...", "url": "...", "original_author": { "username": "someothercreator", "display_name": "Some Other Creator", "sec_uid": "MS4wLjABAAAA...", "avatar_url": "https://.../avatar.jpg", "verified": true } }, "occurred_at": null } ``` #### tiktok.live.started / tiktok.live.ended Both events carry the same room_id for one live session, so an alert can be opened on start and closed on end. occurred_at is null on LIVE frames. ```ts { "type": "tiktok.live.started", "object": { "room_id": "...", "previous_state": "...", "current_state": "...", "session_generation": 1 }, "occurred_at": null } ``` #### tiktok.media.ready The playable/downloadable file for a tracked video is now fetchable. This frame repeats an already-announced event_id — match it to the original content event rather than rendering a second post. It is the only place a playable URL appears: tenant frames never include a raw TikTok play_url. Fetch the file from object.media_url: a short-lived signed URL that needs no API key (the bare /v1/media/{video_id}.mp4 path without its exp/sig signature returns 403). ```ts // SEPARATE schema — "1322.tiktok.media.v1", NOT event.v1. No account, no sequence. { "schema": "1322.tiktok.media.v1", "event_id": "01J9Z8QX4T7C2V1M0K3R5B6N7P", "type": "tiktok.media.ready", "platform": "tiktok", "observed_at": "2026-08-22T14:03:40Z", "object": { "video_id": "7300000000000000000", "url": "https://www.tiktok.com/@examplecreator/video/7300000000000000000", "media_url": "https://tiktok.1322.io/v1/media/7300000000000000000.mp4?exp=...&sig=..." } } ``` ### TikTok type definitions #### TiktokEvent (content frame, schema 1322.tiktok.event.v1) ```ts export type TiktokEventType = | "tiktok.upload.created" // video, photo or carousel post | "tiktok.repost.created" | "tiktok.live.started" | "tiktok.live.ended"; export interface TiktokEvent { schema: "1322.tiktok.event.v1"; event_id: string; // unique per event — use for dedup sequence?: number; // monotonic per stream, when present type: TiktokEventType; platform: "tiktok"; // verified is present as true ONLY when the creator is verified; absent otherwise. account: { sec_uid?: string; username?: string; display_name?: string; verified?: true }; object?: TiktokEventObject; // Uploads carry a timestamp; reposts and LIVE frames send null. // Sort on observed_at for a total order across every type. occurred_at?: string | null; // ISO-8601, when TikTok published it observed_at: string; // ISO-8601, when 1322 emitted the event delivery?: { mode: "live_only" }; // live stream only — no backfill or replay } ``` #### TiktokMediaReadyEvent (media frame, schema 1322.tiktok.media.v1) ```ts // tiktok.media.ready is a SEPARATE schema with a different, smaller shape — // no account, no sequence. It repeats an already-announced event_id once the // media is fetchable, and is NOT a second post. export interface TiktokMediaReadyEvent { schema: "1322.tiktok.media.v1"; event_id: string; // matches the content event this media belongs to type: "tiktok.media.ready"; platform: "tiktok"; observed_at: string; object: { video_id?: string; url?: string; media_url?: string }; } ``` #### TiktokEventObject ```ts export interface TiktokOriginalAuthor { sec_uid?: string; username?: string; display_name?: string; avatar_url?: string; verified?: true; // present only when verified; absent otherwise } // What the post actually is, so you can branch without inspecting media. export type ContentKind = "video" | "photo" | "carousel"; export interface MusicInfo { title?: string; author_name?: string; original?: true; // the creator's own sound, not a licensed track duration?: number; // seconds } export interface TiktokEventObject { // upload / repost video_id?: string; url?: string; kind?: ContentKind; title?: string; description?: string; cover_url?: string; // Parsed out of description. hashtags arrive WITHOUT the leading #, // mentions WITHOUT the leading @. mentions?: string[]; hashtags?: string[]; duration?: number; // video length in seconds music?: MusicInfo; // Playable file. There is deliberately NO play_url — tenant frames never // include the raw TikTok play_url, so reading it always yields undefined. media_url?: string; // playable file — arrives on tiktok.media.ready image_urls?: string[]; // photo posts and carousels, instead of a video avatar_url?: string; original_author?: TiktokOriginalAuthor; // on tiktok.repost.created — an OBJECT, not a username string // live.started / live.ended room_id?: string; previous_state?: string; current_state?: string; session_generation?: number; } ``` #### Tracked creator record (GET /v1/list) ```ts // Rows returned by the live API carry: track_id, username, sec_uid, // events, state, ws_delivery, discord_delivery. export interface TiktokTrackedAccount { track_id: string; username: string; sec_uid?: string; events: string[]; // subset of ["upload", "repost", "live"] state: string; // e.g. "active" ws_delivery: boolean; discord_delivery: boolean; display_name?: string; discord_channel_id?: string | null; added_at?: string | number; } ``` ### TikTok notes - REST uses your API key. WebSocket uses a separate WebSocket key. Do not mix them. Each side accepts two headers: REST takes X-API-Key: or Authorization: Bearer ; WebSocket takes X-WS-Key: or Authorization: Bearer . The api_key sent as X-WS-Key returns 401, and query-string keys are not enabled on either side. - WebSocket connection: wss://tiktok.1322.io, where ws_path is GET /v1/ws/status -> path, or GET /v1/dashboard -> websocket.path. Handshake failures before upgrade: 401 wrong/missing key, 403 expired tenant or WebSocket disabled or origin denied, 404 wrong path, 429 connection limit. Success is 101. - Two frame schemas: content events (upload/repost/live.started/live.ended) use 1322.tiktok.event.v1; tiktok.media.ready uses 1322.tiktok.media.v1 with a smaller shape (no account, no sequence). - Payload traps: object.original_author is an OBJECT ({sec_uid, username, display_name, avatar_url, verified}), not a username string. There is no object.play_url on any tenant frame — the playable file is object.media_url on the media.ready frame. object.image_urls (string[]) carries photo posts and carousels, which have no video. occurred_at is set on uploads and null on reposts and LIVE frames. - object.kind is "video" | "photo" | "carousel" and discriminates the post type without inspecting media. object.mentions and object.hashtags are string[] parsed from the description — hashtags arrive without the leading # and mentions without the leading @, so add the symbol back when rendering. object.duration is video length in seconds. object.music is {title?, author_name?, original?, duration?}, where original is true only for the creator's own sound. object.title carries the post title where TikTok supplies one separately from description. - account.verified and object.original_author.verified are present as true ONLY when the creator is verified and are ABSENT otherwise — test for presence, never for a false value. - Public probes, no authentication: GET /health and GET /healthz for liveness, GET /readyz for readiness. GET /v1/health also exists but requires the API key. Point uptime monitors at the public probes rather than polling an authenticated endpoint. - Expiry: client.expires_at is RFC3339 and appears in GET /v1/status and GET /v1/dashboard once a term has been set. It is ABSENT (not null) when no term has been set yet — that is a real state, not an unsupported feature. - Creators are tracked by username or sec_uid. sec_uid is stable across username changes; track_id is the handle returned by POST /v1/track and GET /v1/list, and accepted by POST /v1/untrack. - Delivery: WebSocket and REST always; Discord bot delivery additionally when the client is linked to a Discord server (discord_enabled on GET /v1/status, discord_delivery per tracked creator). - delivery.mode is "live_only" — events are not queued while your client is disconnected. Reconnect with exponential backoff; dedup by event_id across reconnects. - WebSocket connection ceilings: 16 concurrent connections per account, 8 per IP (GET /v1/limits, GET /v1/ws/status). - Reference: GET /openapi.json and GET /v1/docs on tiktok.1322.io. - Call the API from your own server, never from browser code: your API key must stay private, and the REST endpoints are not built for cross-origin (CORS) browser requests. ## Binance Square (platform id: binance-square) Real-time tracking of Binance Square creators via binance.1322.io. Monitors posts, pin changes, polls, quotes, media, sentiment (bullish/bearish), coin pairs, and engagement metrics, delivered via WebSocket with per-tenant isolation. - REST base: https://binance.1322.io - WebSocket: wss://binance.1322.io/{ws_path}?key={ws_key} — Path and WS key are provided in your dashboard configuration (returned by GET /v1/dashboard). - Authentication: All endpoints require the X-Api-Key header with your API key. WebSocket: connect with your API key via the key= query parameter. - Rate limit: Per-key rate limits apply. Standard HTTP status codes (401, 403, 429) are used for errors. ### Binance Square management endpoints #### GET /v1/dashboard Returns full dashboard data including tracked accounts, service status, and WebSocket connection info. (authentication required) Request example: ``` curl "https://binance.1322.io/v1/dashboard" \ -H "X-Api-Key: YOUR_API_KEY_HERE" ``` Response example: ``` { "status": "ok", "tracked": ["CZ_Binance", "binaborz"], "current": 2, "max_tracked": 10, "ws_path": "/v1/ws", "ws_key": "your_ws_key" } ``` #### POST /v1/track Add a Binance Square user to your tracking list. Send the username in the JSON body. (authentication required) Request example: ``` curl -X POST "https://binance.1322.io/v1/track" \ -H "Content-Type: application/json" \ -H "X-Api-Key: YOUR_API_KEY_HERE" \ -d '{"username": "CZ_Binance"}' ``` Response example: ``` { "status": "ok", "tracked": { "username": "CZ_Binance", "square_uid": "123456789", "display_name": "CZ", "avatar_url": "https://...", "added_at": "2025-01-15T12:00:00Z" } } ``` #### POST /v1/untrack Remove a Binance Square user from your tracking list. Send the username in the JSON body. (authentication required) Request example: ``` curl -X POST "https://binance.1322.io/v1/untrack" \ -H "Content-Type: application/json" \ -H "X-Api-Key: YOUR_API_KEY_HERE" \ -d '{"username": "CZ_Binance"}' ``` Response example: ``` { "status": "ok", "account": "CZ_Binance", "tracked": ["binaborz"], "current": 1, "max_tracked": 10 } ``` ### Binance Square WebSocket event types #### binance.post data is a BinancePost for binance.post frames. ```ts // Every WS frame is { type, data }. Branch on type. export type WsEventType = "binance.post" | "binance.pin.update"; export interface WsEnvelope { type: WsEventType; data: BinancePost | PinUpdate; } ``` #### binance.pin.update data is a PinUpdate for binance.pin.update frames. ```ts export interface PinUpdate { username: string; display_name?: string; avatar_url?: string; square_uid?: string; added?: BinancePost[]; // newly pinned posts removed?: BinancePost[]; // unpinned posts removed_ids?: string[]; note?: string; // hint only; confirm on Square if needed detected_at: string; // RFC3339 event time } ``` ### Binance Square type definitions #### BinancePost ```ts export interface BinancePost { id: string; username: string; display_name?: string; avatar_url?: string; square_uid?: string; content_type?: string; // "post" | "video" | "space" | "article" title?: string; text?: string; web_link?: string; share_link?: string; is_reply: boolean; parent_id?: string; // Engagement reply_count?: number; like_count?: number; comment_count?: number; share_count?: number; view_count?: number; // Sentiment tendency?: string; // "bullish" | "bearish" | "" bullish_ratio?: number; bearish_ratio?: number; coin_pairs?: string[]; // ["BTCUSDT", "ETHUSDT"] hashtags?: string[]; mentions?: string[]; // Rich content media?: MediaItem[]; poll?: PostPoll; quote?: PostQuote; // Embedded quote/repost reply_to?: PostQuote; // Parent post context translation?: PostTranslation; live_replay?: SpaceLiveReplay; resolved_links?: PostResolvedLink[]; published_at: string; // ISO 8601 detected_at: string; // ISO 8601 } ``` #### PostQuote (quote / reply_to / nested share this shape — the referenced/parent post) ```ts export interface PostQuote { id?: string; username?: string; display_name?: string; avatar_url?: string; text?: string; link?: string; published_at?: string; // ISO 8601, when Binance provides it tendency?: string; // "bullish" | "bearish" | "" bullish_ratio?: number; bearish_ratio?: number; coin_pairs?: string[]; hashtags?: string[]; mentions?: string[]; links?: PostLink[]; media?: MediaItem[]; poll?: PostPoll; nested?: PostQuote; // quote-of-quote, when present translation?: PostTranslation; } ``` #### Sub-types (media / poll / translation / links / live_replay) ```ts export interface MediaItem { kind: "image" | "video" | "gif" | string; url: string; preview?: string; mime_type?: string; width?: number; height?: number; duration_s?: number; scope?: "post" | "quote" | "quote_nested" | "reply_to"; } export interface PostPoll { question?: string; total_votes?: number; ends_at?: string; closed?: boolean; options?: { label?: string; value?: string; votes?: number; ratio?: number }[]; } export interface PostTranslation { body?: string; source_language?: string; target_language?: string; need_translate?: boolean; } export interface PostLink { url: string; kind?: string; domain?: string; label?: string; } export interface PostResolvedLink { kind: string; label: string; url: string; raw?: string; } export interface SpaceLiveReplay { title?: string; duration_s?: number; replay_url?: string; status?: number; live_type?: number; live_status?: number; view_count?: number; audio_web_url?: string; content_type?: string; } ``` ### Binance Square notes - content_type: "post" | "video" | "space" | "article". tendency: "bullish" | "bearish" | "" (empty string). coin_pairs is an array of trading pairs mentioned, e.g. ["BTCUSDT", "ETHUSDT"]. detected_at is the ISO-8601 timestamp of when 1322 first detected the post. - Replies: the author and their reply text are the MAIN card (is_reply=true, parent_id set); the post they replied to is under reply_to (a PostQuote with the parent's username/display_name/avatar_url/text/link/published_at). reply_to is present when Binance provides the parent. quote, reply_to and nested all share the PostQuote shape. - Call the API from your own server, never from browser code: your API key must stay private, and the REST endpoints are not built for cross-origin (CORS) browser requests. ## News (platform id: news) Real-time aggregation from major news sources via newsfeed.1322.io. Articles are processed immediately upon detection with full text extraction, media, and categorization. Delivered via per-server WebSocket streams. - REST base: https://newsfeed.1322.io - WebSocket: wss://newsfeed.1322.io/{ws_path}?key={ws_key} — Path and WS key are provided in your dashboard configuration (e.g. /news_459f182...). NOTE: the backend's GET /v1/dashboard currently returns ws_url with host news.1322.io, which is NXDOMAIN (dead) — the working WS host is newsfeed.1322.io, same as REST. Until the backend is fixed, connect on newsfeed.1322.io regardless of the ws_url host. - Authentication: All endpoints require the X-Api-Key header with your API key. WebSocket: connect with your API key via the key= query parameter. - Rate limit: Per-key rate limits apply. Standard HTTP status codes (401, 403, 429) are used for errors. ### News management endpoints #### GET /v1/dashboard Returns full dashboard data including subscribed feeds, service status, and WebSocket connection info (ws_path, ws_key). (authentication required) Request example: ``` curl "https://newsfeed.1322.io/v1/dashboard" \ -H "X-Api-Key: YOUR_API_KEY_HERE" ``` Response example: ``` { "status": "ok", "feeds": ["BBC News", "NYPost", "Bloomberg"], "current": 3, "max_feeds": 18, "ws_path": "/v1/ws", "ws_key": "your_ws_key" } ``` #### POST /v1/subscribe Subscribe to a news feed to receive articles via WebSocket. Send the feed name in the JSON body. (authentication required) Request example: ``` curl -X POST "https://newsfeed.1322.io/v1/subscribe" \ -H "Content-Type: application/json" \ -H "X-Api-Key: YOUR_API_KEY_HERE" \ -d '{"feed": "BBC News"}' ``` Response example: ``` { "status": "ok", "feed": "BBC News", "feeds": ["BBC News", "NYPost", "Bloomberg"], "current": 3, "max_feeds": 18 } ``` #### POST /v1/unsubscribe Unsubscribe from a news feed. Send the feed name in the JSON body. (authentication required) Request example: ``` curl -X POST "https://newsfeed.1322.io/v1/unsubscribe" \ -H "Content-Type: application/json" \ -H "X-Api-Key: YOUR_API_KEY_HERE" \ -d '{"feed": "BBC News"}' ``` Response example: ``` { "status": "ok", "feed": "BBC News", "feeds": ["NYPost"], "current": 1, "max_feeds": 18 } ``` ### News WebSocket event types #### LIVE_POST (every WS message is a WebSocketNewsFeedPayload with _event_type: "LIVE_POST") guid is the recommended dedup key. full_text is the complete extracted article body. ```ts export interface WebSocketNewsFeedPayload { feed: string; // Provider: "BBC News" | "NYPost" | "Fox News" | ... guid: string; // Unique article ID (typically URL hash) — use for dedup url: string; // Full article URL title: string; publish_time: string; // ISO-8601 modified_time?: string; primary_category: string; categories: string[]; author: string; keywords: string[]; description: string; summary: string; media: NewsMediaAttachment[]; full_text: string; // complete extracted article body text language?: string; copyright?: string | null; _event_type: "LIVE_POST"; _sent_time: string; // ISO-8601 dispatch timestamp } ``` ### News type definitions #### NewsMediaAttachment ```ts export interface NewsMediaAttachment { url: string; // Visual asset URL type: "image" | "video"; caption?: string; } ``` ### News notes - Available feeds (21 total): NYPost, BBC News, BBC Sport, BBC Business, Daily Mail News, Daily Mail Sport, Daily Mail Money, Decider, Fox News, CBSNews World, CBSNews Top, CNBC, Al Jazeera, NYTimes, The Verge, Dexerto, Bloomberg, Wired, Washington Times, Forbes, NVIDIA. - Call the API from your own server, never from browser code: your API key must stay private, and the REST endpoints are not built for cross-origin (CORS) browser requests.