API and developers

Schedule Posts via API: A Developer's Guide

Scheduling posts across multiple social platforms via API doesn't have to mean juggling five OAuth flows. Here's how to do it in one request with the OmniSocials API.

Robert LigthartFounder of OmniSocialsPublished Updated 12 min read
Schedule Posts via API: A Developer's Guide

If you've tried scheduling social media posts programmatically, you know the drill. Instagram's Graph API requires a two-step media container flow. LinkedIn's API needs a separate app registration with its own OAuth. TikTok's posting endpoints are behind an app review process that takes weeks. And that's before you've touched X, YouTube, or Pinterest.

Key takeaways

  • To schedule a post with the OmniSocials API, send POST /v1/posts with content, a channels array, and a future scheduled_at timestamp in ISO 8601.
  • Leave out scheduled_at to save a draft, or use POST /v1/posts/create-and-publish to post right away.
  • There is no bulk endpoint: loop over your posts, one request each, within the limit of 100 requests per minute per API key.
  • Signed webhooks report five events: post.scheduled, post.published, post.failed, post.approved, and post.rejected.
  • OmniSocials costs $10 per seat a month billed yearly; Ayrshare starts at $149 a month and Buffer at $5 per channel a month billed yearly (checked October 18, 2026).
On this page
  1. Key takeaways
  2. What Is a Schedule Posts API?
  3. Why Native Platform APIs Are Painful
  4. Step 1: Get Your API Key
  5. Step 2: Connect Your Social Accounts
  6. Step 3: Schedule a Post via the API
  7. JavaScript Example
  8. Python Example
  9. Step 4: Handle the Response
  10. Check Post Status
  11. Cancel a Scheduled Post
  12. Scheduling in Bulk
  13. Setting Up Webhooks
  14. OmniSocials vs. Doing It Natively
  15. Common Pitfalls
  16. Frequently Asked Questions
  17. Sources

The OmniSocials API solves this with a single endpoint. One POST request, one API key, up to 13 platforms. No platform-specific OAuth in your code. No separate app registrations. This guide walks through everything you need to schedule posts via API in 2026.


What Is a Schedule Posts API?

A schedule posts API lets you programmatically queue social media content to publish at a specific future time, without manual intervention. Instead of logging into a dashboard and clicking "Schedule," you send a structured HTTP request with your content, target platforms, and a publish timestamp.

OmniSocials wraps 13 social platforms into one unified scheduling API. Connect your accounts once in the dashboard, then use a single API key to schedule across Instagram, LinkedIn, TikTok, YouTube, X, Facebook, Pinterest, Bluesky, Threads, Mastodon, Google Business Profile, Telegram, and Discord.

[Screenshot: OmniSocials API key settings page with a newly generated API key]


Why Native Platform APIs Are Painful

Before showing the OmniSocials approach, it's worth understanding what you're avoiding.

Instagram's native API requires you to create a media container (step 1), wait for it to be ready (step 2), then publish it (step 3). For carousels, add a fourth step. For Reels, add video processing time. And your app needs to pass Facebook's App Review before it can post to any real accounts.

LinkedIn's API requires a separate OAuth 2.0 flow per user, a URN for the author, a different payload structure for images vs. text-only posts, and specific scopes approved during partner review.

TikTok's Content Posting API is invite-only as of 2026. You apply, wait, and hope.

You'd need to build and maintain five separate integrations just to cover the major platforms. The OmniSocials API removes all of that.


Step 1: Get Your API Key

Sign in to your OmniSocials account (or start a 14-day free trial if you haven't yet). Navigate to Settings > API and create a new API key (it starts with omsk_live_).

Store it as an environment variable. Never hardcode it in your source.

export OMNISOCIALS_API_KEY="omsk_live_your_key_here"

Step 2: Connect Your Social Accounts

In the OmniSocials dashboard, connect whichever platforms you want to post to. This is the only time you'll deal with OAuth flows. From here on, your code uses one API key for everything.

This is the key architectural difference from building native integrations yourself. The OAuth complexity lives in OmniSocials's infrastructure, not yours.


Step 3: Schedule a Post via the API

Send a POST request to https://api.omnisocials.com/v1/posts with three fields:

  • content: your post text (a string, or an object with a default caption plus per-platform overrides)
  • channels: array of platforms to post to, such as instagram, linkedin, x, bluesky
  • scheduled_at: ISO 8601 timestamp for when to publish. It must be in the future. Leave it out and the post is saved as a draft.

Attach media with media_urls (public file URLs that OmniSocials downloads for you) or media_ids (files you uploaded earlier).

JavaScript Example

const response = await fetch('https://api.omnisocials.com/v1/posts', {
  method: 'POST',
  headers: {
    'Authorization': `Bearer ${process.env.OMNISOCIALS_API_KEY}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    content: 'Our new feature just dropped. Check it out at the link below.',
    channels: ['instagram', 'linkedin', 'bluesky'],
    media_urls: ['https://yourcdn.com/feature-announcement.jpg'],
    scheduled_at: '2027-03-02T09:00:00Z',
  }),
});

const { data } = await response.json();
console.log(data.id, data.status); // "1019" "scheduled"

Python Example

import os
import requests

response = requests.post(
    'https://api.omnisocials.com/v1/posts',
    headers={'Authorization': f'Bearer {os.environ["OMNISOCIALS_API_KEY"]}'},
    json={
        'content': 'Our new feature just dropped. Check it out at the link below.',
        'channels': ['instagram', 'linkedin', 'bluesky'],
        'media_urls': ['https://yourcdn.com/feature-announcement.jpg'],
        'scheduled_at': '2027-03-02T09:00:00Z',
    },
)
response.raise_for_status()

data = response.json()['data']
print(data['id'])      # 1019
print(data['status'])  # scheduled

Prefer a client library? The official OmniSocials SDKs for Node.js, Python, Go, Rust, .NET, Java, PHP, and Ruby wrap this same request as client.posts.create(), with retries on 429 and 5xx responses built in.

To publish right away instead of scheduling, send the same body to POST /v1/posts/create-and-publish (or add "publish_now": true).


Step 4: Handle the Response

The API answers 201 with the post in data. The status field moves through these values:

  • scheduled: queued, waiting for its publish time
  • posting: being published right now
  • published: live, with a link per platform in published_urls
  • failed or warning: every platform, or some platforms, failed. The reason per platform is in errors.

Use the id to check status later, update the post, or cancel it.

Check Post Status

const postId = '1019';

const response = await fetch(`https://api.omnisocials.com/v1/posts/${postId}`, {
  headers: {
    'Authorization': `Bearer ${process.env.OMNISOCIALS_API_KEY}`,
  },
});

const { data } = await response.json();
console.log(data.status, data.published_urls, data.errors);

Cancel a Scheduled Post

await fetch(`https://api.omnisocials.com/v1/posts/${postId}`, {
  method: 'DELETE',
  headers: {
    'Authorization': `Bearer ${process.env.OMNISOCIALS_API_KEY}`,
  },
});
// Removes the post from OmniSocials, so it never publishes

To move a post instead of deleting it, send PATCH /v1/posts/{id} with a new scheduled_at.


Scheduling in Bulk

Need to schedule a week's worth of content at once? Each post is its own request, so loop over your content calendar:

const posts = [
  {
    content: 'Monday motivation. Start the week right.',
    channels: ['linkedin', 'threads'],
    scheduled_at: '2027-03-01T08:00:00Z',
  },
  {
    content: 'Mid-week check-in. How are your goals coming along?',
    channels: ['threads', 'bluesky'],
    scheduled_at: '2027-03-03T10:00:00Z',
  },
  {
    content: 'Friday wrap-up. Here is what we shipped this week.',
    channels: ['linkedin', 'bluesky', 'x'],
    scheduled_at: '2027-03-05T16:00:00Z',
  },
];

for (const post of posts) {
  const response = await fetch('https://api.omnisocials.com/v1/posts', {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${process.env.OMNISOCIALS_API_KEY}`,
      'Content-Type': 'application/json',
    },
    body: JSON.stringify(post),
  });
  const { data } = await response.json();
  console.log(data.id, data.schedule_at);
}

The rate limit is 100 requests per minute per API key, which is more than enough for typical scheduling workflows. If you do hit it, the API answers 429 with a Retry-After header.


Setting Up Webhooks

Instead of polling for post status, register a webhook to get notified automatically when something happens. Add your HTTPS endpoint in the OmniSocials dashboard under Settings > API, or with POST /v1/webhooks. You can subscribe to these events:

  • post.scheduled: a post was scheduled
  • post.published: post went live
  • post.failed: post failed on one or more platforms
  • post.approved and post.rejected: a post in an approval workflow was reviewed

Every delivery is signed with an X-OmniSocials-Signature header (t=<unix>,v1=<hex>, an HMAC-SHA256 over {t}.{rawBody}). The Node.js SDK checks it for you:

// Express webhook handler example
import express from 'express';
import { verifyWebhookSignature } from '@omnisocials/sdk';

const app = express();

app.post(
  '/webhooks/omnisocials',
  express.raw({ type: 'application/json' }), // verify the raw body
  (req, res) => {
    const event = verifyWebhookSignature({
      payload: req.body,
      signature: req.get('X-OmniSocials-Signature') ?? '',
      secret: process.env.OMNISOCIALS_WEBHOOK_SECRET,
    });

    if (event.type === 'post.published') {
      console.log(`Post ${event.data.post_id} published:`, event.data.targets);
    }

    if (event.type === 'post.failed') {
      console.error(`Post ${event.data.post_id} failed:`, event.data.targets);
      // Trigger retry logic or alert your team
    }

    res.sendStatus(200);
  },
);

Each target in event.data.targets carries the platform, its status, and an error when that platform failed.


OmniSocials vs. Doing It Natively

Here's a concrete comparison. Scheduling the same post to Instagram and LinkedIn:

StepNative APIsOmniSocials API
Step: AuthNative APIs: 2 separate OAuth flowsOmniSocials API: 1 API key
Step: App registrationsNative APIs: 2 (Facebook + LinkedIn)OmniSocials API: 0
Step: API calls to scheduleNative APIs: 3 (Instagram) + 1 (LinkedIn) = 4OmniSocials API: 1
Step: Platform review requiredNative APIs: Yes (both)OmniSocials API: No
Step: Media handlingNative APIs: Manual per platformOmniSocials API: Built-in (media_urls or one upload)
Step: MaintenanceNative APIs: Update if APIs changeOmniSocials API: OmniSocials handles it

The native approach requires maintaining two separate codepaths that can break independently. OmniSocials absorbs platform changes so your integration doesn't.


Common Pitfalls

Timezone mistakes. The API expects UTC timestamps. 2027-03-02T09:00:00Z means 9 AM UTC, not 9 AM in your local timezone. If your users set times in their local timezone, convert to UTC before sending.

Scheduling in the past. If scheduled_at is earlier than the current time when OmniSocials processes the request, the API rejects it with a 400 validation error (schedule_at must be in the future). Add a buffer of at least a few minutes, and use the create-and-publish call when you mean "now."

Platform-specific content limits. Instagram captions max out at 2,200 characters. X cuts off at 280. If your content is 1,000 characters and you include x in your channels array, the API rejects the post with a 400 instead of cutting your text. Pass content as an object ({ default: '...', x: '...' }) to give X its own shorter version. Check the API docs for per-platform character limits if you're posting cross-platform with long copy.

Missing media for Instagram. Instagram (and TikTok) require an image or video. A text-only post with channels: ['instagram'] returns a 400 validation error, and the whole request is rejected, so the other channels in it don't get the post either. Attach media, or send Instagram its own request.

Not storing the post ID. Always persist the id from the API response. You'll need it to check status, update content, or cancel before publishing.


Frequently Asked Questions

How do I schedule a social media post via API?

Send a POST request to https://api.omnisocials.com/v1/posts with your content, a channels array, and a future scheduled_at timestamp in ISO 8601 format. Include your API key in the Authorization: Bearer header. The API returns the post, with its ID and a scheduled status, right away. Get your API key at omnisocials.com.

Can I schedule posts to multiple platforms in one API call?

Yes. The OmniSocials API accepts an array of channel names in a single POST request, covering up to 13 platforms simultaneously: Instagram, LinkedIn, TikTok, YouTube, X, Facebook, Pinterest, Bluesky, Threads, Mastodon, Google Business Profile, Telegram, and Discord. Native platform APIs each require a separate integration with their own auth flow and endpoint structure.

What is the best API for scheduling social media posts?

OmniSocials is a cost-effective option at $10 per seat a month billed yearly, with full API access across 13 platforms. Ayrshare's cheapest plan is $149 a month ($129 billed yearly) and its network list has 14 entries. Buffer prices per channel, from $5 per channel a month billed yearly (prices checked October 18, 2026). For developers building automation workflows in 2026, OmniSocials offers a strong price-to-platform ratio and a simple auth model.

How do I cancel a scheduled post via API?

Send a DELETE request to https://api.omnisocials.com/v1/posts/{post_id} using the post ID returned when you created the post. A scheduled post is removed before it publishes, so it never goes out on any platform. Deleting a post that already published only removes it from OmniSocials; the live post stays up on the platforms.

Does the OmniSocials API support webhooks for scheduled posts?

Yes. Register a webhook URL under Settings > API (or with POST /v1/webhooks) to receive post.scheduled, post.published, post.failed, post.approved, and post.rejected events. This is better than polling GET /v1/posts/:id for status, especially in production workflows where you need to react quickly to failures.


The OmniSocials API is built for exactly this use case: developers who want to schedule posts at scale without the overhead of maintaining five separate platform integrations. The full API reference, including all endpoints, payload options, and error codes, is at docs.omnisocials.com.


Sources

Written byRobert LigthartFounder of OmniSocials

Try OmniSocials for 14 days

Plan, schedule and answer on 13 platforms from one calendar, or let your AI agent do it. The first charge comes when the trial ends.