universal-social-sdk
v1.1.2
Published
TypeScript-first universal social media SDK for Node.js
Maintainers
Readme
universal-social-sdk
TypeScript-first, ESM-only, zero-bloat Node.js SDK that provides one unified interface for X, Facebook, Instagram, LinkedIn, YouTube, TikTok, Pinterest, Bluesky, Mastodon, and Threads.
Documentation
- Project Structure
- NPM Package Guide
- Response Contracts
- Contributing
- Roadmap v1.1.0
- Code of Conduct
- Security Policy
- Changelog
Install
npm install universal-social-sdkQuick Start
import { Instagram, X, Facebook, LinkedIn } from "universal-social-sdk";
await X.postTweet({ text: "Hello from universal SDK!" });
await Instagram.uploadReel({
videoUrl: "https://example.com/reel.mp4",
caption: "Hello world"
});
await Facebook.publishToPage({
message: "Shipping updates from one SDK"
});
await LinkedIn.createTextPost({
text: "Cross-platform publishing with one API"
});
import { YouTube, TikTok, Pinterest, Bluesky, Mastodon, Threads } from "universal-social-sdk";
await YouTube.listMyVideos({ maxResults: 5 });
await TikTok.listVideos({ maxCount: 10 });
await Pinterest.listBoards({});
await Bluesky.postText({ text: "Hello AT Protocol!" });
await Mastodon.createStatus({ text: "Hello Fediverse!" });
await Threads.postText({ text: "Hello Threads!" });Examples
Run bundled examples:
npm run example:x
npm run example:instagram
npm run example:bluesky
npm run example:queueFiles:
examples/x-post.mjsexamples/instagram-reel.mjsexamples/bluesky-post.mjsexamples/queue-in-memory.mjs
Queue Adapters
The scheduler uses a queue adapter. By default it uses an in-memory adapter.
import { InMemoryQueueAdapter, setQueueAdapter } from "universal-social-sdk";
setQueueAdapter(new InMemoryQueueAdapter());Adapter exports:
InMemoryQueueAdapter(default behavior)BullMQAdapter(skeleton)SQSAdapter(skeleton)
The scheduler APIs (for example X.scheduleTweet) will use the active adapter automatically.
Typed Responses
All public SDK methods now return concrete TypeScript interfaces, including platform-specific action/delete aliases for clearer contracts.
Action/delete/mutation/detail responses are normalized into stable contracts (success, action/targetId/resourceId, raw) so provider endpoint changes are isolated to SDK internals.
import { X } from "universal-social-sdk";
import type { XPostResult } from "universal-social-sdk";
const result: XPostResult = await X.postTweet({ text: "typed response" });
console.log(result.data.id);Webhooks
The SDK includes webhook utilities for Meta-style and X-style signatures, normalized event parsing, and a lightweight router.
import {
WebhookRouter,
verifyMetaWebhookSignature,
verifyXWebhookSignature
} from "universal-social-sdk";
const router = new WebhookRouter();
router.on("meta.feed", async (event) => {
console.log("Meta feed event", event.payload);
});
router.on("x.tweet_create_events", async (event) => {
console.log("X tweet event", event.payload);
});Required Environment Variables
universal-social-sdk auto-loads .env with dotenv.
X / Twitter
X_API_KEYX_API_SECRETX_ACCESS_TOKENX_ACCESS_SECRETX_BEARER_TOKEN(optional for some read-only operations)X_CLIENT_ID(OAuth 2 workflows)X_CLIENT_SECRET(OAuth 2 workflows)
Meta (Facebook Pages + Instagram Graph)
META_APP_IDMETA_APP_SECRETFB_PAGE_ACCESS_TOKENFB_PAGE_IDIG_ACCESS_TOKENIG_USER_IDMETA_GRAPH_VERSION(defaultv21.0)
LINKEDIN_ACCESS_TOKENLINKEDIN_REFRESH_TOKEN(recommended for long-running apps)LINKEDIN_CLIENT_IDLINKEDIN_CLIENT_SECRETLINKEDIN_ORG_URNorLINKEDIN_PERSON_URNLINKEDIN_API_VERSION(default202510)
YouTube
YOUTUBE_ACCESS_TOKENYOUTUBE_CHANNEL_ID
TikTok
TIKTOK_ACCESS_TOKENTIKTOK_OPEN_IDTIKTOK_ADVERTISER_ID
PINTEREST_ACCESS_TOKENPINTEREST_BOARD_ID
Bluesky
BLUESKY_SERVICE_URL(defaulthttps://bsky.social)BLUESKY_IDENTIFIERBLUESKY_APP_PASSWORDBLUESKY_ACCESS_JWTBLUESKY_REFRESH_JWT
Mastodon
MASTODON_BASE_URLMASTODON_ACCESS_TOKENMASTODON_ACCOUNT_ID
Threads
THREADS_ACCESS_TOKENTHREADS_USER_ID
SDK / Updater
SOCIAL_SDK_MAX_RETRIES(default3)SOCIAL_SDK_RETRY_BASE_MS(default500)UPDATER_LLM_PROVIDER(openrouterorollama, defaultopenrouterwhen API key is present, otherwiseollama)UPDATER_LLM_BASE_URL(defaulthttps://openrouter.ai/api/v1)UPDATER_LLM_API_KEY(orOPENROUTER_API_KEY)UPDATER_LLM_MODEL(orOPENROUTER_MODEL, defaultgoogle/gemma-3-4b-it:freefor OpenRouter,llama3.2:3bfor Ollama)UPDATER_LLM_APP_NAME(optional request metadata)UPDATER_LLM_APP_URL(optional request metadata)UPDATER_LLM_MAX_TOKENS(default1200)UPDATER_LLM_MAX_DOC_CHARS_PER_PAGE(default6000)UPDATER_LLM_MAX_ENDPOINT_ROWS_PER_PAGE(default40)UPDATER_LLM_MAX_MODEL_ATTEMPTS(default4)UPDATER_LLM_FALLBACK_MODELS(comma-separated OpenRouter model IDs used after primary model fails)OLLAMA_HOST(legacy local runtime support, defaulthttp://127.0.0.1:11434)OLLAMA_MODEL(legacy local runtime support)
CLI
Bootstrap
npx universal-social-sdk initCreates .env.example, copies it to .env if missing, and prints OAuth setup links:
- X Developer Portal: https://developer.x.com/en/portal/dashboard
- Meta Developers: https://developers.facebook.com/apps/
- LinkedIn Developers: https://www.linkedin.com/developers/apps
Documentation Updater
npx universal-social-sdk updatenpx universal-social-sdk update --dry-run
npx universal-social-sdk update --model llama3.2
npx universal-social-sdk update --fallback-models "google/gemma-3-4b-it:free,qwen/qwen3-4b:free"
npx universal-social-sdk update --max-model-attempts 5
npx universal-social-sdk update --yes
npx universal-social-sdk update --ci --open-pr --base main --branch-prefix chore/updaterFlow:
- Crawls official docs pages for X, Meta Graph API, Instagram Graph API, and LinkedIn.
- Extracts clean text and table-like endpoint data with Cheerio.
- Sends doc snapshots to your configured LLM provider (OpenRouter or local runtime).
- In OpenRouter mode, retries across a fallback model chain for
402/404/408/429model-level failures with a short backoff between attempts.
- In OpenRouter mode, retries across a fallback model chain for
- Requests generated method updates + full TypeScript file content.
- Runs safety checks to reject suspicious placeholder rewrites or destructive class replacements.
- Shows git-style diffs and asks for confirmation.
- Applies patches and rebuilds package.
CI/PR mode writes deterministic artifacts in .artifacts/:
update-plan.jsonupdate-diff-summary.jsonpr-title.txtpr-body.md
Supported Methods
Method coverage by platform:
X: posting, threads, replies, quote posts, likes, retweets, DMs, analytics, schedulingFacebook: page publishing, stories, comments, reactions, insights, scheduled postsInstagram: media/reels/stories, carousels, comments, moderation, insightsLinkedIn: text/image/video/carousel posts, comments, likes, analytics, media uploadYouTube: upload sessions, metadata updates, playlists, comments, channel analyticsTikTok: video publish flow, comments/replies, likes, status checks, analyticsPinterest: pin/board management, comments/replies, pin/account analyticsBluesky: text posts, links, replies, likes/reposts, feed/search/thread retrievalMastodon: statuses, media posts, favourites/boosts, context, schedulingThreads: text/image/video posts, replies, likes, thread/account insights
Complete method list is maintained in supported-methods.json.
OAuth Setup Guide
X
- Open https://developer.x.com/en/portal/dashboard.
- Create a Project and App.
- Enable OAuth 1.0a and OAuth 2.0, then generate user tokens.
- Add credentials into
.env. - Screenshot to keep: App keys and user token generation page.
Meta (Facebook + Instagram Graph)
- Open https://developers.facebook.com/apps/.
- Create app, add Facebook Login + Instagram Graph API products.
- Get Page access token (
pages_manage_posts,pages_read_engagement, etc.). - Map Page to Instagram professional account and capture
IG_USER_ID. - Screenshot to keep: App Review permissions and Access Token Debugger output.
- Open https://www.linkedin.com/developers/apps.
- Create app and add Marketing APIs / Community Management products.
- Configure OAuth 2.0 redirect URLs and request required scopes.
- Exchange auth code for access token (and refresh token if enabled).
- Screenshot to keep: Products enabled page + OAuth scopes configuration.
YouTube
- Open https://console.cloud.google.com/apis/library/youtube.googleapis.com.
- Enable YouTube Data API v3 for your project.
- Configure OAuth consent and create OAuth client credentials.
- Exchange user authorization for
YOUTUBE_ACCESS_TOKEN.
TikTok
- Open https://developers.tiktok.com/.
- Create app, configure login scopes and redirect URI.
- Complete OAuth flow and store long-lived
TIKTOK_ACCESS_TOKEN.
- Open https://developers.pinterest.com/.
- Create app and configure OAuth redirect URI/scopes.
- Obtain
PINTEREST_ACCESS_TOKENand targetPINTEREST_BOARD_ID.
Bluesky
- Open https://bsky.app/settings/app-passwords.
- Create an app password for your account.
- Set
BLUESKY_IDENTIFIERandBLUESKY_APP_PASSWORD.
Mastodon
- Register an application on your Mastodon instance.
- Generate an access token with write/read scopes.
- Set
MASTODON_BASE_URL,MASTODON_ACCESS_TOKEN, andMASTODON_ACCOUNT_ID.
Threads
- Open https://developers.facebook.com/docs/threads.
- Create app, request Threads API scopes, and generate user token.
- Set
THREADS_ACCESS_TOKENandTHREADS_USER_ID.
Error Handling
All errors are normalized to SocialError.
import { SocialError, X } from "universal-social-sdk";
try {
await X.postTweet({ text: "hello" });
} catch (error) {
if (error instanceof SocialError) {
console.error(error.platform, error.endpoint, error.message, error.statusCode);
}
}Rate Limit Handling
- Automatic retries on
429and5xx. - Exponential backoff defaults:
500ms,1000ms,2000ms. - Configure with:
SOCIAL_SDK_MAX_RETRIESSOCIAL_SDK_RETRY_BASE_MS
Legal / Terms Notes
- You must comply with each platform’s Terms of Use, policy docs, and display requirements.
- Some actions require app review, partner approval, business verification, or specific account types.
- Messaging APIs (especially DMs) are often restricted to approved use cases.
Testing
npm run test:unit
npm run test:integrationIntegration tests are environment-gated. Create .env.test from .env.test.example and use sandbox credentials.
Integration Test Env Matrix
| Platform | Required .env.test keys | Required CI secrets |
| --- | --- | --- |
| X | X_API_KEY, X_API_SECRET, X_ACCESS_TOKEN, X_ACCESS_SECRET, X_TEST_TWEET_ID | X_API_KEY, X_API_SECRET, X_ACCESS_TOKEN, X_ACCESS_SECRET, X_TEST_TWEET_ID |
| Facebook | FB_PAGE_ACCESS_TOKEN, FB_PAGE_ID | FB_PAGE_ACCESS_TOKEN, FB_PAGE_ID |
| Instagram | IG_ACCESS_TOKEN, IG_USER_ID | IG_ACCESS_TOKEN, IG_USER_ID |
| LinkedIn | LINKEDIN_ACCESS_TOKEN, LINKEDIN_ORG_URN | LINKEDIN_ACCESS_TOKEN, LINKEDIN_ORG_URN |
| YouTube | YOUTUBE_ACCESS_TOKEN, YOUTUBE_CHANNEL_ID | YOUTUBE_ACCESS_TOKEN, YOUTUBE_CHANNEL_ID |
| TikTok | TIKTOK_ACCESS_TOKEN | TIKTOK_ACCESS_TOKEN |
| Pinterest | PINTEREST_ACCESS_TOKEN, PINTEREST_BOARD_ID | PINTEREST_ACCESS_TOKEN, PINTEREST_BOARD_ID |
| Bluesky | BLUESKY_IDENTIFIER, BLUESKY_APP_PASSWORD (BLUESKY_TEST_ACTOR optional) | BLUESKY_IDENTIFIER, BLUESKY_APP_PASSWORD, BLUESKY_TEST_ACTOR |
| Mastodon | MASTODON_BASE_URL, MASTODON_ACCESS_TOKEN, MASTODON_ACCOUNT_ID | MASTODON_BASE_URL, MASTODON_ACCESS_TOKEN, MASTODON_ACCOUNT_ID |
| Threads | THREADS_ACCESS_TOKEN, THREADS_USER_ID | THREADS_ACCESS_TOKEN, THREADS_USER_ID |
GitHub Actions
This repo includes:
.github/workflows/ci.ymlfor build + unit tests on every push/PR..github/workflows/release.ymlfor npm publish on tag (v*) or manual dispatch..github/workflows/auto-update-pr.ymlfor scheduled doc crawling + updater PR generation.- Generates
.artifacts/*for PR metadata during the run but does not commit artifact files.
- Generates
Manual dry-run option for updater workflow:
- In Actions -> Auto Update PR -> Run workflow, set
dry_run=trueto run detection and artifact generation only (no branch/PR).
Configure these repository secrets to enable integration CI:
X_API_KEYX_API_SECRETX_ACCESS_TOKENX_ACCESS_SECRETX_TEST_TWEET_IDFB_PAGE_ACCESS_TOKENFB_PAGE_IDIG_ACCESS_TOKENIG_USER_IDLINKEDIN_ACCESS_TOKENLINKEDIN_ORG_URNYOUTUBE_ACCESS_TOKENYOUTUBE_CHANNEL_IDTIKTOK_ACCESS_TOKENPINTEREST_ACCESS_TOKENPINTEREST_BOARD_IDBLUESKY_IDENTIFIERBLUESKY_APP_PASSWORDBLUESKY_TEST_ACTOR(optional; defaults toBLUESKY_IDENTIFIERwhen omitted)MASTODON_BASE_URLMASTODON_ACCESS_TOKENMASTODON_ACCOUNT_IDTHREADS_ACCESS_TOKENTHREADS_USER_ID
Configure this repository secret for publishing:
NPM_TOKEN
Configure this repository secret for scheduled updater PRs:
UPDATER_LLM_PROVIDER(openrouterorollama)UPDATER_LLM_API_KEY(required foropenrouter; or useOPENROUTER_API_KEY)UPDATER_LLM_MODEL(optional)UPDATER_LLM_BASE_URL(optional; defaults to OpenRouter URL)UPDATER_LLM_MAX_TOKENS(optional; cap completion size/cost)UPDATER_LLM_MAX_MODEL_ATTEMPTS(optional)UPDATER_LLM_FALLBACK_MODELS(optional comma-separated model chain)
Alternative OpenRouter-compatible secret names also supported:
OPENROUTER_API_KEYOPENROUTER_MODEL
