Skip to main content

Social media scheduling API

How to Schedule Social Media Posts with an API

Scheduling through an API removes the nightly manual posting routine. Your backend submits the week of content once with a future timestamp, the queue holds each post until its time, and the team checks status instead of watching a clock. This page shows the scheduling request, the fields it accepts, what the queue does with it, and how to follow a post through to publication.

What scheduling through an API actually changes

Content teams that publish across five platforms end up keeping five calendars, or one spreadsheet and five alarms. Moving the timing into the system collapses that: one backend job owns the schedule, and a person owns the content. The same endpoint covers every supported platform, so a multi-platform week is one integration instead of five. What does not move into the system is the content itself. Each platform still has its own media rules and length limits, and the API rejects a payload that breaks them before the post is queued.

Schedule a post from your backend

Scheduling uses POST /api/posts with a scheduledAt timestamp. The payload carries the content, the account IDs to target, a media type, and the settings for each platform. The sample below schedules a text post to a Facebook Page. Media posts use the same shape with mediaType set to video or photo and a mediaUrls array instead of text.

const API_BASE_URL = 'https://api.wahdx.com';
const API_KEY = process.env.WAHDX_API_KEY;

const headers = {
  'X-API-Key': API_KEY,
  'Content-Type': 'application/json'
};

// Schedule a text-only post
await fetch(API_BASE_URL + '/api/posts', {
  method: 'POST',
  headers,
  body: JSON.stringify(
    {
      "platform": "facebook",
      "mediaType": "text",
      "content": "Scheduled text-only post",
      "accountIds": [
        "FACEBOOK_ACCOUNT_ID"
      ],
      "scheduledAt": "2026-08-01T09:00:00.000Z"
    }
  )
});

Fields in the scheduling request

These are the fields that decide where the post goes and when. Everything except scheduledAt also applies to an immediate post, so the same payload works for both once you remove the timestamp.

Fields accepted by POST /api/posts
FieldRequiredWhat it does
contentYesThe caption or post text. Length is validated against the strictest platform in the target set.
accountIdsYesArray of connected account IDs. Every ID must resolve to an active account owned by your workspace.
mediaTypeYesvideo, photo, or text. Text is limited to Threads and Facebook Pages.
mediaUrlsFor media postsArray of public media URLs. Omit it when mediaType is text.
scheduledAtFor scheduled postsISO 8601 timestamp in the future, at most 30 days out. Omit it to publish immediately.
platformNoDefaults to tiktok. Publishing is dispatched per account, so a mixed target set still routes correctly.
tiktokSettings, instagramSettings, threadsSettings, facebookSettings, youtubeSettingsNoPer-platform options, such as privacy level, carousel cover, or reply settings.

How the queue handles a scheduled post

A post created with scheduledAt lands in the queue with a pending status. A server-side scheduler checks for due posts every 60 seconds, claims each one so two workers cannot process the same row, and publishes to the selected accounts. Nothing depends on a browser staying open, and no request from your side has to run at the scheduled minute. It also means the exact publish time can land a few seconds after the timestamp, since the work starts on the next scheduler pass.

  • The queue runs server-side and is checked every 60 seconds.
  • A post is claimed before processing, so it is not published twice.
  • Only successful publishes count toward the monthly upload quota.
  • A failed post stays visible in status tracking and can be resubmitted.
  • Scheduling more than 30 days ahead is rejected at request time.

Rules that are enforced before the post is queued

Validation happens when you submit, not when the post is due. A payload that breaks a platform rule fails immediately with a message you can act on, which is easier to debug than a post that silently fails days later. The checks below cover the cases that come up most often.

  • A text post aimed at TikTok, Instagram, or YouTube is rejected, because those platforms need media.
  • A photo post aimed at YouTube is rejected, since YouTube accepts video only.
  • An account ID that is inactive or belongs to another workspace is rejected, so a post never publishes to a partial target set.
  • Content longer than the strictest target platform allows is rejected, and YouTube is measured in UTF-8 bytes rather than characters.
  • A schedule date in the past, or more than 30 days ahead, is rejected.
  • TikTok accounts are capped at 15 posts per day, checked before the post enters the queue.

Track a scheduled post through to publication

A scheduled post moves through pending, processing, completed, or failed. Poll the status endpoint for one post, or the batch endpoint when a nightly job sweeps the day of content. Both return the per-account result, including a publish ID and a public post URL when the platform provides one. Design the integration to surface those four states to whoever runs the calendar, because a failed post that nobody notices is the same as a post that never went out.

const API_BASE_URL = 'https://api.wahdx.com';
const API_KEY = process.env.WAHDX_API_KEY;

await fetch(API_BASE_URL + '/api/content/status/batch', {
  method: 'POST',
  headers: {
    'X-API-Key': API_KEY,
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    checks: [
      { accountId: 'ACCOUNT_ID_1', publishId: 'PUBLISH_ID_1', mediaType: 'video' },
      { accountId: 'ACCOUNT_ID_2', publishId: 'PUBLISH_ID_2' }
    ]
  })
});

What to check before you trust the schedule

Run one real post through the whole path before you move a week of content onto it. Submit a post two minutes in the future, watch it move from pending to processing to completed, and confirm the public URL works. Then test the failure path on purpose: schedule a text post to a TikTok account and confirm you get a clear rejection instead of a queued post that fails later. Those two tests reveal more about the integration than a week of scheduled content will.

FAQ

Common questions about scheduling

How do I schedule a post with the API?

Send a POST request to /api/posts with content, accountIds, mediaType, and a future scheduledAt timestamp. The post is queued and published server-side when the time arrives.

How far ahead can I schedule a post?

Up to 30 days ahead. A schedule date in the past or beyond that window is rejected when you submit the request.

Will the post publish at the exact minute I set?

The scheduler checks for due posts every 60 seconds, so publishing starts on the next pass after the timestamp. Expect a small delay rather than an exact second.

Can I schedule text-only posts?

Yes, on Threads and Facebook Pages. Set mediaType to text. Scheduling a text post to TikTok, Instagram, or YouTube is rejected before it is queued, because those platforms need media.

What happens to a scheduled post that fails?

It shows as failed in status tracking and does not count toward the monthly upload quota, so you can fix the content and resubmit it.

Does scheduling need a browser open?

No. The queue runs server-side, so scheduled posts publish without anyone keeping a page open. Your backend only needs to submit the request.