Scheduler says published, but the post never appeared
The worst failure mode in social publishing: your tool reports success, but nothing is on the platform. Why it happens and how per-target delivery evidence catches it.
Because a scheduler's green checkmark usually means its own internal job finished, not that the platform confirmed content exists. Publishing is a chain of calls that runs after your request is accepted, and any step can fail late or silently. The only honest proof is target-level: the platform's own returned post ID and a permalink.
Every social publishing tool eventually produces this ticket: the calendar shows a green checkmark, the dashboard says published, and the post is not on the platform. Not delayed, not processing — just not there. The marketer who scheduled it has already moved on to the next campaign, because the tool told them it was done.
This is the worst failure mode in the category, and it is rarely discussed in public because it is uncomfortable to admit: an API returning 200 OK is not the same claim as a post existing on Instagram, LinkedIn, or TikTok. Most tools conflate the two anyway, because distinguishing them requires infrastructure most vendors have not built.
PostGate handles OAuth, publishing and delivery evidence for every network through one API. Start free or read the docs.
Why do "published" and "on the platform" diverge?
Publishing to a social network is not one call — it is a short chain of calls, and the chain runs after your request has already been accepted. A caption gets attached to media, a container gets created, the container gets submitted, and the platform confirms. Any one of those steps can failafter the step before it succeeded, and after your tool has already told you the job is queued or running.
- A transient platform-side failure lands between two calls that both looked successful on their own — the container is created, but the publish call that finalizes it times out or 5xxs.
- A container or draft object is accepted by the platform, then silently discarded on the platform's side without an error ever reaching the caller — nothing to catch, because nothing was returned to catch.
- The publishing tool marks its own job as done the moment it hands the request off internally, rather than waiting for the platform's own confirmation that content exists at a real, addressable post ID.
None of these require anything unusual. They are the ordinary failure modes of a distributed system talking to another company's distributed system, over the public internet, with no shared transaction.
Why is this more damaging than an outright failure?
A visible failure is annoying but honest — the marketer sees red, retries or escalates, and the calendar reflects reality. A false published is worse, because it removes the signal that would have triggered a fix. The campaign calendar says done. The client report says done. Nobody checks a green checkmark.
The gap is usually discovered downstream and late: a customer mentions they never saw the post, an agency gets asked why engagement is at zero, or a launch announcement simply never reached the audience it was scheduled for. By the time anyone notices, the scheduled moment — a product launch, a live event, a time-sensitive promotion — has passed and cannot be recovered by simply retrying.
Why is acceptance not proof of publication?
PostGate treats the response to POST /api/posts as acceptance of the request, not confirmation that content exists on any platform. Delivery for each destination is asynchronous and tracked independently, and the honest state of a post is only knowable by reading targets, not by the shape of the create response.
Each target progresses through pending, media_ready, and publishing, sometimes through reconciling or retry_scheduled when a transient failure needs another attempt, and only then reaches a terminal outcome: published, failed, or skipped. A "published" target carries the platform's own returned post ID and permalink — proof the destination network created something real, not just proof that PostGate's own API returned successfully.
curl https://api.postgate.studio/api/posts/post_01JXYZ \
-H "Authorization: Bearer $POSTGATE_API_KEY"
{
"id": "post_01JXYZ",
"status": "partial",
"targets": [
{
"profile_id": "pro_instagram123",
"status": "published",
"platform_post_id": "17895...",
"permalink": "https://instagram.com/p/Cxyz.../",
"attempts": 1
},
{
"profile_id": "pro_linkedin456",
"status": "failed",
"error": { "code": "platform_transient", "retryable": true },
"attempts": 3
}
]
}"Partial" is a successful, terminal result — not an error to hide
A post sent to five profiles rarely fails or succeeds as a unit. A partial post has at least one published target and at least one failed or skipped target, and it is a legitimate terminal state, not a bug. Tools that only expose a single aggregate status are forced to round a partial result up to "published" or down to "failed" — and rounding up is what produces this exact failure mode at scale.
The correct response to a partial result is to keep the successful permalinks and act only on the failed destinations, which is only possible when the tool exposes target-level state in the first place.
How do you catch it before the customer does?
Polling GET /api/posts/{id} works, but it puts the burden of discovery on your client and adds latency between the platform-side failure and your product noticing it. Subscribing to post.published, post.partial, and post.failed webhooks means PostGate pushes the terminal, evidence-backed outcome to your system the moment every target resolves — including the platform post ID and permalink for anything that actually went live.
Combined with a stable Idempotency-Key on the original create call, this makes the whole lifecycle safe to reason about: you know exactly what was accepted, exactly what happened per destination, and you never have to guess whether a retry will double-post a target that already succeeded.
Frequently asked questions
What causes a scheduled social post to silently never appear?
Three ordinary failure modes: a transient platform-side failure lands between two calls that each looked successful — the container is created, but the publish call that finalizes it times out or 5xxs; the platform accepts a container or draft, then silently discards it without returning an error; or the tool marks its own job done at internal handoff instead of waiting for the platform's confirmation at a real post ID.
Why is a false "published" worse than a visible failure?
A visible failure is annoying but honest — the marketer sees red, retries or escalates, and the calendar reflects reality. A false published removes the signal that would have triggered a fix, so the gap is discovered downstream and late — zero engagement, a customer who never saw it. By then the scheduled moment has passed and cannot be recovered by retrying.
What does a "partial" post status mean, and is it a bug?
A partial post has at least one published target and at least one failed or skipped target — a legitimate terminal state, not a bug. Tools exposing only one aggregate status must round a partial result up to published or down to failed, and rounding up produces exactly this failure mode. The correct response is to keep the successful permalinks and act only on the failed destinations.
How do I detect a failed social post before the customer notices?
Subscribe to the post.published, post.partial, and post.failed webhooks so the terminal, evidence-backed outcome — including the platform post ID and permalink for anything that went live — is pushed to your system the moment every target resolves. Combined with a stable Idempotency-Key on the create call, you also never have to guess whether a retry will double-post a target that already succeeded.
