OmniSocialsOmniSocials
DocumentationAPI reference
Help centerSupport
  • Documentation
  • API reference
Developers
  • Quickstart
  • API reference
  • SDKs
  • MCP server
  • CLI
For AI agents
  • Docs for AI agents
  • llms.txt
  • OpenAPI spec
  • Postman collection
Product
  • OmniSocials
  • Pricing
  • Changelog
  • Help center
Company
  • Support
  • Privacy policy
  • Terms of service

© 2026 OmniSocials

OmniSocials on GitHubOmniSocials on XOmniSocials on LinkedIn
Overview
Get started
SDKs
    Node.jsPythonGoRubyJavaPHP.NETRust
CLI
MCPDocs for AI agentsWebhooks
Guides
Platforms
Integrations
Migrate
Plans and billing
GlossaryChangelogAPI reference
SDKs

Node.js SDK reference: install, auth and methods

The official Node.js / TypeScript SDK. Zero runtime dependencies (native fetch), Node 18+, ships ESM and CommonJS, fully typed.

This page is the reference. For an overview of the Node.js SDK, see omnisocials.com/sdk/nodejs.

Install

TerminalTerminal
npm install @omnisocials/sdk

Authentication

TypeScript
import { OmniSocials } from "@omnisocials/sdk"; const client = new OmniSocials({ apiKey: "omsk_live_..." }); // or set OMNISOCIALS_API_KEY and call new OmniSocials()

CommonJS: const { OmniSocials, verifyWebhookSignature } = require("@omnisocials/sdk");

Create a post

TypeScript
const { data: post } = await client.posts.create({ content: "New drop this Friday", channels: ["instagram", "facebook", "linkedin"], scheduled_at: "2026-08-01T09:00:00Z", media_urls: ["https://example.com/teaser.jpg"], }); console.log(post.id, post.status);

Any media_urls (or media_ids) entry can also be an object carrying per-media alt text (max 1500 chars), delivered to Mastodon, Bluesky, X (photos), Pinterest, Instagram (images), and LinkedIn (images):

TypeScript
media_urls: [{ url: "https://example.com/teaser.jpg", alt: "Red sneaker on a white background" }],

Publish immediately:

TypeScript
await client.posts.createAndPublish({ content: "Going live right now", channels: ["x", "bluesky"], });

Upload media

TypeScript
const upload = await client.media.uploadFromUrl({ url: "https://example.com/launch-video.mp4", name: "launch-video-v2", folder: "Campaigns", }); console.log(upload.data.id, upload.compatibility);

Local files via multipart:

TypeScript
// From a path const res = await client.media.upload({ file: "./photos/product.jpg", name: "product-hero" }); // Or from bytes / a Blob import { readFile } from "node:fs/promises"; const bytes = await readFile("./photos/product.jpg"); await client.media.upload({ file: bytes, filename: "product.jpg" });

Analytics

TypeScript
// One post's latest per-platform metrics const { data: stats } = await client.analytics.post("post_id"); console.log(stats.platforms.instagram?.metrics); // Batch: up to 100 posts in one call const batch = await client.analytics.posts(["id1", "id2", "id3"]); // Workspace-wide overview const { data: overview } = await client.analytics.overview({ period: "30d" }); console.log(overview.total_impressions, overview.total_engagements); // Account-level stats (followers etc) const accounts = await client.analytics.accounts({ platform: "instagram" });

Social Inbox

Read and answer DMs, comments and mentions from your connected accounts. The API key needs the opt-in inbox:read / inbox:write scopes. The lists use cursor pagination (cursor in, pagination.next_cursor out).

TypeScript
const { data: conversations } = await client.inbox.listConversations({ platform: "instagram", unread: true, }); const conversationId = conversations[0].conversation_id; const { data: messages } = await client.inbox.getMessages(conversationId); await client.inbox.reply(conversationId, { text: "Thanks for reaching out!" }); await client.inbox.markRead(conversationId); // Comment moderation: hide (pass { hide: false } to unhide) or delete await client.inbox.hide(messages[0].id); await client.inbox.deleteMessage(messages[0].id);

inbox.next() hands out the next conversation that still needs an answer, with the thread and the post it belongs to. On a comment thread, pass message_id so the reply goes under the comment you answer and not under the newest comment on the post.

TypeScript
let { data: item, remaining } = await client.inbox.next(); while (item) { if (!item.reply_window.open) { // An Instagram/Facebook DM past Meta's 24-hour window: answer it in the app await client.inbox.markRead(item.message.conversation_id); ({ data: item, remaining } = await client.inbox.next()); continue; } const reply = await client.inbox.reply(item.message.conversation_id, { text: "Thanks! DM sent.", message_id: item.message.id, include_next: true, }); item = reply.next ?? null; remaining = reply.remaining ?? 0; }

See the Social Inbox guide for the platforms, the reply rules and the error codes.

Pinterest product tags

Tag products on a Pin so people can shop the items in the image. List the product Pins of the connected Pinterest account, then pass up to 24 of their Pin ids as product_tags in the pinterest options of the post. Only product Pins of your own account can be tagged; products of other merchants cannot.

TypeScript
const list = await client.pinterest.listProducts(); if (list.error) { console.warn(list.error.code, list.error.message); } else { await client.posts.create({ content: "Our summer picks", channels: ["pinterest"], media_urls: ["https://example.com/summer-look.jpg"], scheduled_at: "2026-08-01T09:00:00Z", pinterest: { board_id: "1234567890", product_tags: (list.products ?? []).slice(0, 3).map((product) => product.pin_id), }, }); }

The list answers with HTTP 200 in both cases: products on success, or an error object (pinterest_not_connected, pinterest_catalog_access_required, platform_error) when it could not be read. It reads the Pinterest catalog when the connection has catalog access (given one time in the OmniSocials composer: Pinterest options, Add products, Connect catalog), else the account's own Pins. The tags are added right after the Pin is published. A product that Pinterest refuses never fails the post: the post then carries pinterest.product_tags_result with the tagged and the skipped Pin ids. client.pinterest.validateProduct(id) checks one Pin id or Pin link before you post. On posts.update() the pinterest object replaces the stored one, so leave product_tags out to remove the tags.

Verify webhooks

TypeScript
import express from "express"; import { verifyWebhookSignature, WebhookVerificationError } from "@omnisocials/sdk"; const app = express(); app.post( "/omnisocials/webhook", express.raw({ type: "application/json" }), // keep the raw body! (req, res) => { try { const event = verifyWebhookSignature({ payload: req.body, // Buffer of the raw body signature: req.get("X-OmniSocials-Signature") ?? "", secret: process.env.OMNISOCIALS_WEBHOOK_SECRET!, tolerance: 300, // seconds (default) }); switch (event.type) { case "post.published": console.log("Published:", event.data.post_id, event.data.targets); break; case "post.failed": console.error("Failed:", event.data.post_id); break; case "post.rejected": console.warn("Rejected:", event.data.post_id, event.data.approval?.reason); break; } res.sendStatus(200); } catch (err) { if (err instanceof WebhookVerificationError) { return res.sendStatus(400); } throw err; } } );

Events: post.scheduled, post.published, post.failed, post.approved and post.rejected. The two approval events carry data.approval with status, decided_by (the approver's user id) and reason (null on post.approved). To read the full review of a post (steps, approvers, the rejection reason and the comment thread), call client.posts.getApproval(id).

Errors

The base class is OmniSocialsError. API errors are APIError subclasses carrying status, code, message, and body: ValidationError (400/422), AuthenticationError (401), PermissionDeniedError (403), NotFoundError (404), RateLimitError (429, with .retryAfter), ServerError (5xx), plus APIConnectionError and WebhookVerificationError.

TypeScript
import { APIError, RateLimitError, ValidationError, APIConnectionError } from "@omnisocials/sdk"; try { await client.posts.create({ content: "Hi", channels: ["instagram"] }); } catch (err) { if (err instanceof RateLimitError) { console.warn(`Rate limited, retry in ${err.retryAfter}s`); } else if (err instanceof ValidationError) { console.error(`Bad request (${err.code}): ${err.message}`, err.body); } else if (err instanceof APIConnectionError) { console.error("Network problem:", err.message); } else if (err instanceof APIError) { console.error(`API error ${err.status} (${err.code}): ${err.message}`); } else { throw err; } }

Configuration

TypeScript
const client = new OmniSocials({ apiKey: "omsk_live_...", baseUrl: "https://api.omnisocials.com/v1", // default timeout: 30_000, // per-request timeout in ms (default 30s) maxRetries: 2, // automatic retries on 429 / 5xx / network errors (default 2) });

Note that timeout is in milliseconds; the other SDKs use seconds or durations.

Notes

  • Responses destructure as { data }; list endpoints return { data, pagination }
  • 204 deletes resolve to null
  • client.health() returns { status, version, timestamp }
  • Source: github.com/OmniSocials/omnisocials-node
Last modified on October 21, 2026
SDKsPython
On this page
  • Install
  • Authentication
  • Create a post
  • Upload media
  • Analytics
  • Social Inbox
  • Pinterest product tags
  • Verify webhooks
  • Errors
  • Configuration
  • Notes
TypeScript
TypeScript
TypeScript
TypeScript
TypeScript
TypeScript
TypeScript
TypeScript
TypeScript
TypeScript
TypeScript
TypeScript
TypeScript