TypeScript SDK
Use the SDK when you control the TypeScript runtime and want the least abstraction between your app or agent and the platform publishers. The REST server, Scheduler app, CLI, and MCP server all build on this package.
Install
The SDK is public on npm and does not require a GitHub token or custom package registry. Install it with your normal package manager:
npm install @simple-post/sdk
# or
yarn add @simple-post/sdk
# or
pnpm add @simple-post/sdk
Quick start
Set TELEGRAM_BOT_TOKEN to your bot token and TELEGRAM_CHAT_ID to a channel username (such as @mychannel) or numeric chat ID. Add the bot to that chat with permission to post. The example passes the chat ID explicitly; the SDK does not load it automatically.
import { post } from "@simple-post/sdk";
const botToken = process.env.TELEGRAM_BOT_TOKEN;
const chatId = process.env.TELEGRAM_CHAT_ID;
if (!botToken || !chatId) throw new Error("Set TELEGRAM_BOT_TOKEN and TELEGRAM_CHAT_ID");
const results = await post({
content: { text: "Hello from SimplePost" },
platforms: ["telegram"],
options: { telegram: { chatId, credentials: { botToken } } },
});
const result = results.get("telegram");
console.log(result);
A successful Telegram result contains the message ID and error: "NO_ERROR". post() returns a Map keyed by the requested platforms; inspect every result because multi-platform publishing can partially fail. See Telegram setup for bot creation and permissions.
The quickstart is checked against published SDK 1.3.1. Platform guides distinguish that release from newer hosted/core behavior; see release scope.
Posting model
The SDK uses a Post payload. Other interfaces translate their own inputs into this model; REST account IDs and MCP message fields are not SDK fields. After configuring credentials for X, YouTube, and Instagram, plus public media storage:
await post({
content: {
text: "Check out this video",
media: [
{
type: "video",
path: "./video.mp4",
title: "Launch demo",
},
],
},
platforms: ["x", "youtube", "instagram"],
options: {
common: { logLevel: "info", strictMode: false },
youtube: { privacyStatus: "unlisted" },
},
});
Media can be a local path where the runtime can read the file, or a public url. Some platforms, especially Instagram and Threads, require public media URLs under the hood. SimplePost can upload temporary public media when storage is configured.
Provider setup
SDK users usually manage provider credentials themselves. You can provide credentials in two ways:
- Environment variables, which are convenient for local tools and single-account services.
options.<platform>.credentials, which is better when your app stores per-user OAuth tokens.
Start with the platform guide for each provider you want to post to:
| Platform | Key | Guide |
|---|---|---|
| X | x | X setup |
| Telegram | telegram | Telegram setup |
instagram | Instagram setup | |
facebook | Facebook setup | |
| Threads | threads | Threads setup |
| TikTok | tiktok | TikTok setup |
| YouTube | youtube | YouTube setup |
pinterest | Pinterest setup | |
linkedin | LinkedIn setup | |
| Bluesky | bluesky | Bluesky setup |
Common patterns
Text post
await post({
content: { text: "Hey, this is a simple post" },
platforms: ["x", "facebook"],
});
Media post
await post({
content: {
text: "Here are some photos",
media: [
{ type: "image", path: "./image1.jpg" },
{ type: "image", path: "./image2.jpg" },
],
},
platforms: ["x", "instagram"],
});
X reply or thread segment
await post({
content: { text: "Great point." },
platforms: ["x"],
options: {
x: { replyToId: "1234567890" },
},
});
Telegram channel
Telegram requires the chatId option for every post — it is not read from any env var. The bot token is read from TELEGRAM_BOT_TOKEN or supplied through options.telegram.credentials.botToken.
await post({
content: { text: "Hello Telegram" },
platforms: ["telegram"],
options: {
telegram: { chatId: "@mychannel", parseMode: "HTML" },
},
});
Strict mode
By default, SimplePost adapts content to platform limits when it can. For example, a platform with a lower image limit may receive fewer images than another platform. Enable strict mode to fail instead:
await post({
content: { text: "Cross-platform post" },
platforms: ["x", "bluesky"],
options: {
common: { strictMode: true },
},
});
Token refresh
Some OAuth providers rotate refresh tokens. X is the most important case: every successful X refresh returns a new refresh token and invalidates the old one. The SDK does not persist refreshed credentials for you. If a result contains extraData.refreshedCredentials, store those values before the next post.
const refreshed = results.get("x")?.extraData?.refreshedCredentials;
if (refreshed) {
await saveUserTokens(refreshed);
}
Examples
The repository includes examples under core/examples, including:
examples/x/postThread.tsexamples/instagram/postCarousel.tsexamples/tiktok/postVideo.tsexamples/youtube/postVideoFull.tsexamples/all/postVideo.ts
Run examples from the core/examples workspace after setting the relevant provider credentials.