---
title: "Scheduling social media posts through an API: why 'scheduled' does not mean 'published'"
description: "A scheduling API that answers HTTP 200 has accepted the post, not published it; publishing happens later and can fail separately on each network. In the period we measured, our poster logged success on every run while all 17 Facebook posts and 12 Instagram posts failed. We now read the final status per network after the publish time, expire every cached list of connected accounts, and check generated captions in code, on the text that actually leaves."
date: 2026-10-11
lang: en
canonical: https://goingstellar.ro/methods/scheduled-is-not-published-social-posting-api/
author: Going Stellar
publisher: GOING STELLAR S.R.L.
topic: E-commerce / Social media
license: CC BY 4.0
alternate_ro: https://goingstellar.ro/ro/metode/programat-nu-inseamna-publicat-postari-sociale/
---

# Scheduling social media posts through an API: why "scheduled" does not mean "published"

*A scheduling API that answers HTTP 200 has accepted the post, not published it; publishing happens later and can fail separately on each network. In the period we measured, our poster logged success on every run while all 17 Facebook posts and 12 Instagram posts failed. We now read the final status per network after the publish time, expire every cached list of connected accounts, and check generated captions in code, on the text that actually leaves.*

> E-commerce · Social media · 2026-10-11 · https://goingstellar.ro/methods/scheduled-is-not-published-social-posting-api/

## Key points

- An HTTP 200 from a social media scheduling API means the post was accepted for scheduling, not that any network published it.
- Publishing can fail separately on each network, so read the final status per network after the publish time before reporting success or raising the cadence.
- Every cached list of connected social accounts needs an expiry; a stale list sends posts to networks that are no longer connected, and the failure appears nowhere.
- Prompt rules do not guarantee caption quality: check the generated caption in code and correct brand names deterministically on the text that is actually published.
- A corrector applied at the start of a pipeline does not protect text that later steps rewrite; apply deterministic correctors at the common exit.

## What "scheduled" and "published" mean in a social posting API

When you schedule a social media post through an API, a 200 response means the scheduler accepted the request, not that any network published the post. Publishing happens at the scheduled time, separately for each network (TikTok, Instagram, Facebook, YouTube), and each one can fail without changing the response you logged. To know whether a post went out, ask the scheduler for the final status of each network after the publish time.

We publish short vertical videos for several store brands through a third-party scheduling service: one API request carries one video, one caption and a list of networks, and the service publishes to each network at the chosen time. For some pages we also post directly through Meta's Graph API. The difference between accepted and published applies to both paths.

## How our social posting pipeline works

**1. Source.** Edited clips come from a shared drive, one folder per brand. A vision model watches each clip and returns its quality, whether it is on brand, whether it carries another brand's watermark, and a draft caption. Every verdict, rejections included, is stored with the file ID as key, so a clip is never downloaded or judged twice.

**2. Filter the format.** Only real vertical video passes: height greater than width and width divided by height at most 0.65, which is 9:16. Square, 4:5 and landscape clips get bars added by the platforms. A second check asks the model whether bars are burned into the picture, for example a landscape clip placed on a vertical canvas. Duplicates are matched on normalised name plus duration; one clip had been uploaded 8 times under slightly different names.

**3. Queue.** A daily refill job tops up each brand's queue when it falls below a minimum (first 3 items, refilled to 5; now 4, refilled to 7). A brand with nothing new in its folder costs nothing and resumes on its own when content appears.

**4. Post.** A daily job drains the queue round robin and schedules the day's posts at fixed hours. The refill and the poster share one lock, because a picker and a poster writing the queue at the same time overwrote the "posted" flags. A separate register of what was posted per brand is the source of truth when the queue is damaged.

**5. Verify.** After the publish time, the status of every network is read back. This step was missing at first, and the next section shows what that cost.

## The failure: HTTP 200 on every run, nothing on two networks

In the period we measured, the poster's log showed HTTP 200 on every run. The status per network said something else: TikTok 17 of 17 published, YouTube 11 of 11 published, Facebook 17 of 17 failed, Instagram 12 failed. The response we logged belonged to the scheduling request; publishing happened later, per network, and its result never reached our log.

The cause underneath was a cache. Our list of brands and their connected networks was a local file 2 months old, read with no expiry, so the poster kept sending Facebook and Instagram to brands whose connections had lapsed. The same stale cache caused a second kind of damage: a profile renamed for a different business kept its internal ID, and content meant for the old business was published on the renamed profile.

The fix has three parts. The connected-networks cache now expires after 12 hours, falling back to the old copy only when the API cannot be reached. The final status of each network is read back from the scheduler; that request needs full ISO date-times, because a compact date format returns 400. And when a post to all networks fails, it is retried without YouTube, so one network rejecting a video does not take the others down.

The request that led us here was "post more often". Had we only raised the cadence, we would have multiplied failed posts and reported success.

## Captions: the model writes them, code checks them

A caption generated from a video can repeat what the person in the video says. On a talking-head clip, a creator introduced themselves by name; the model wrote the caption as if the brand account were that person and turned the name into a meaningless common noun. It went out on three networks, and on YouTube the caption becomes the title, cut mid-word. A scan of the queue found one such case in about 90 captions. Captions in the first person as an anonymous customer ("I tried it") remain allowed; self-introduction by name does not.

The rule now lives in two places: in the prompt, and in a check on the output that asks for one rewrite and rejects the clip if the rewrite fails too. Writing that check had its own trap. A case-insensitive regular expression turned the "capitalised name" pattern into "any word", and the first scan reported 23 broken captions where there was one. Test a check on good and bad examples before believing it.

Brand and product names are corrected deterministically, after the model and before the queue, because the model kept misspelling them: a product line name went out with one wrong letter on three networks, and a third spelling was waiting in the queue. Known misspellings are replaced exactly; a fuzzy match at similarity 0.82 or above handles new ones, only on capitalised words, because in a dry run ordinary lower-case words came close enough to brand names to be "corrected". The list of correct names comes from product titles in the store, not from memory. A corrected or rejected caption must also be fixed in the stored verdict cache, or it returns at the next rebuild.

## Correct the text that actually leaves

The same lesson came from another text pipeline of ours, drafted customer-service replies, and it applies to captions. A deterministic corrector ran once, at the entry of a chain of checks, while at least five later steps rewrote the text, some by regenerating it with a model. The same error came back three times by three different paths, and each time we thought it was fixed. The diagnosis came from running the corrector by hand on the final output: it fixed the text, so the text had never passed through it.

Deterministic correctors for names, punctuation and fixed forms belong at the common exit, on the text that is published. If they are idempotent, run them at entry and at exit. A verifier that rejects a regeneration is not a corrector: it does not clean the first draft.

## Schedules, time zones, hidden caps and platform rules

**Time zone.** The server clock was one hour behind local time, so "now" labelled with the local zone was an hour in the past and the scheduler rejected near-future slots as being in the past. Times are now computed in an explicit zone, independent of the system clock.

**Hidden cap.** The poster takes the first N entries of a list of posting hours, so posts per day can never exceed the number of hours listed: with 13, 15, 18 and 20, the maximum is 4 whatever the slot setting says. Added hours must be later than 10, the hour the daily job runs, or the day's schedule empties and slides to tomorrow. We raised the cadence from 1, 2 and 3 posts a day (other days, Friday, Saturday) to 2, 3 and 4, from 10 to 17 posts a week across 15 brands in rotation.

**Two channels for one brand.** One brand has two YouTube channels; the scheduler publishes to one and our management token belongs to the other, so a wrong title cannot be fixed through the API. A token check that answers "write OK" confirms a channel, not the channel you meant.

**The direct path.** Through the Graph API, a Facebook page post can be scheduled between 10 minutes and 6 months ahead. Our Instagram path cannot schedule and publishes immediately; it needs an image at a public URL and works in two steps: create a media container, wait until it is finished, then publish. Only 8 of our 22 pages had an Instagram account linked. A post to a public page cannot be undone, so the direct tool defaults to a dry run.

## Where we were wrong, and what this does not guarantee

We treated an accepted request as a delivered post, kept a cache of connected accounts with no expiry, and trusted a prompt to prevent a mistake that only a check on the output catches. Each of these looked healthy in our own logs.

Reading the final status proves a post was published, not that it worked. Our performance analysis over 9,404 past TikTok posts found Saturday at 2.6 times the median views of other days, with offer and urgency content on top; that is a correlation in our history, not a test, and the hour pattern may partly be a time-zone artefact.

**Checklist.** Log the scheduling response and, separately, the final status per network; give every cache of connected accounts an expiry; filter clips to real 9:16 and reject burned-in bars; deduplicate by name and duration; share one lock between anything that writes the queue; correct names in code at the exit; check generated captions for impersonation; compute times in an explicit zone; dry-run anything that posts to a public page.

## Questions and answers

### Does a 200 response from a social media scheduling API mean my post is live?

No. A 200 response means the scheduler accepted the post. Publishing happens later, at the scheduled time, and separately for each network, so one network can publish while another fails. In our case the log showed 200 on every run while all 17 Facebook posts failed. Ask the scheduler for the final status of each network after the publish time.

### Why would scheduled posts fail on Facebook and Instagram but work on TikTok?

One common cause is that the Facebook or Instagram connection lapsed in the scheduling service while your system still believes it is connected. Ours read a cached list of connected networks that was 2 months old and had no expiry. Refresh that list regularly, we use 12 hours, and check the per-network status of each post.

### Can I schedule Instagram posts through the Instagram Graph API?

In our integration, no: the Instagram path publishes immediately. It also needs an image at a public URL and works in two steps, creating a media container, waiting until it is finished, then publishing. Facebook page posts can be scheduled through the Graph API between 10 minutes and 6 months ahead. Text-only posts cannot go to Instagram.

### How do I stop AI-written captions from impersonating the person in the video?

State the rule in the prompt, then check the output in code, because the prompt alone is not enough. Our check looks for self-introduction patterns with a capitalised name, asks the model for one rewrite, and rejects the clip if the rewrite fails. Test the check on good and bad captions: a case-insensitive pattern made our first scan report 23 problems where there was one.

### Why can my posting job not schedule more than a few posts a day?

Check whether the number of posts per day is capped by a list of posting hours. Our poster takes the first N hours from that list, so with four hours listed the maximum is 4 posts a day whatever the slot setting says. New hours must also be later than the time the job runs, or the schedule moves to the next day.

## How to cite

**Cite this as:** Going Stellar (2026). *Scheduling social media posts through an API: why "scheduled" does not mean "published"*. GOING STELLAR S.R.L.. https://goingstellar.ro/methods/scheduled-is-not-published-social-posting-api/

```bibtex
@misc{goingstellar2026scheduled,
  title  = {Scheduling social media posts through an API: why "scheduled" does not mean "published"},
  author = {{Going Stellar}},
  year   = {2026},
  url    = {https://goingstellar.ro/methods/scheduled-is-not-published-social-posting-api/},
  note   = {2026-10-11}
}
```

Licence. Free to quote with attribution.

## Also available

- This page as HTML: https://goingstellar.ro/methods/scheduled-is-not-published-social-posting-api/
- Same article in Romanian: https://goingstellar.ro/ro/metode/programat-nu-inseamna-publicat-postari-sociale/
