Post Lifecycle
Every post status, how posts move between them, what you can do in each state, and which webhook fires on each transition.
Every post moves through a small state machine. Knowing which state a post is in tells you exactly what you can still do with it and which webhook to expect next.
draft ──► scheduled ──► publishing ──► published
│ └──► partial
└─────────► failed
published ──► cancelled (via unpublish)Post statuses
| Status | Meaning |
|---|---|
draft | Saved but not going anywhere. The default when you provide no scheduling info. |
scheduled | Has a future scheduledFor (set directly or assigned by a queue). Will be picked up at that time. |
publishing | Currently being delivered to the platforms. Transient. |
published | Every platform target succeeded. |
partial | Some platform targets succeeded, others failed. |
failed | Every platform target failed. |
cancelled | Publishing was cancelled, or the post was removed from the platform via unpublish. |
Which status a new post gets
Create post decides the initial status from the scheduling fields:
| You send | Initial status |
|---|---|
publishNow: true | Publishes immediately. The response already carries the terminal result (published, partial, or failed) including platformPostUrl per platform. |
scheduledFor | scheduled |
queuedFromProfile | scheduled, with scheduledFor assigned from the profile's next free queue slot |
isDraft: true, or none of the above | draft |
Per-platform status and errors
The post-level status is an aggregate. Each entry in platforms[] carries its own state: pending, processing, uploading, published, failed, or cancelled, plus a platformPostUrl on success.
On failure, each platform entry includes a human-readable errorMessage and two machine-readable fields for programmatic handling:
errorCategory | Meaning | Fix |
|---|---|---|
auth_expired | Token expired or revoked | Have the user reconnect the account. Account health catches this early. |
user_content | Content violates platform constraints (format, length, media specs) | Fix the content. See platform requirements. |
user_abuse | Platform rate limits or spam detection | Slow down. See rate limits. |
account_issue | Account configuration problem (e.g. wrong account type) | Fix the account setup on the platform. |
platform_rejected | Platform rejected for policy reasons | Usually needs content changes. |
platform_error | Platform 5xx or maintenance | Transient. Retry later. |
system_error | Zernio-side issue (rare) | Retry, or contact support if persistent. |
unknown | Unclassified | Inspect errorMessage. |
errorSource (user, platform, system) tells you who can fix it: user errors need action from you or your user, platform and system errors are usually worth retrying.
What you can do in each state
| Operation | Allowed states | Notes |
|---|---|---|
| Update | draft, scheduled, failed, partial, cancelled | Published posts can only have their recycling config updated. |
| Delete | Any | Removes the Zernio record. Does not remove already-published content from platforms. |
| Retry | failed, partial | Only the failed platforms are retried; already-published platforms are skipped. |
| Unpublish | published, partial | Deletes the post from the platform; the Zernio record becomes cancelled. Not supported on Instagram, TikTok, or Snapchat. YouTube deletion is permanent. |
| Edit published | published | X (Twitter) only. Requires X Premium on the connected account and must be within 1 hour of publishing. |
Tracking transitions with webhooks
Each transition fires a post webhook. Subscribe instead of polling:
| Event | Fires when |
|---|---|
post.scheduled | A post is scheduled for future publishing |
post.published | All platforms succeeded |
post.partial | Some platforms succeeded, some failed |
post.failed | All platforms failed |
post.cancelled | A publishing job is cancelled |
post.recycled | A recycled post is re-queued |
post.platform.published / post.platform.failed | Per platform target, as soon as that platform reaches a terminal state, without waiting for the others |
post.tiktok.url_resolved | A published TikTok post's public URL becomes available (TikTok resolves URLs asynchronously) |
The per-platform events are the fastest signal: a post targeting five platforms emits them one by one as each platform finishes, while the aggregate event waits for all five.
For immediate publishes (publishNow: true) you don't need webhooks to learn the outcome: the create response is synchronous and already contains the per-platform results and URLs.
Related
- Error handling - error envelope, publishing failures, and retries
- Idempotency & safe retries - avoid double-posting when you retry creates
- Queue scheduling - let Zernio assign the publish time