Docs

Post lifecycle

The states a post and each of its accounts go through, and what you can do with a post in each state.

A post goes to one or more accounts. Each account gets a target with its own status, and the post's status sums up its targets. This page shows how both move and which calls are allowed when.

Post status

A draft is scheduled, and a scheduled post can be cancelled back to a draft. When its time is due it is publishing, and ends as published, partially_failed or failed. A retry sends the failed accounts again and the post is publishing once more.schedulecanceltime dueretry (failed accounts only)draftscheduledpublishingpublishedpartially_failedfailed
StatusMeaning
draftSaved without a time. Nothing happens until you schedule or publish it
scheduledWaiting for its time. publishNow and POST /posts/{id}/publish answer with scheduled too and start sending right away
publishingAt least one account is being sent, or waits for an automatic retry
publishedEvery account published
partially_failedEvery account is done; some published, some failed
failedEvery account is done and none published

Scheduled posts are picked up once a minute, so a post goes out within about a minute of its time.

Target status

Each entry in targets[] has its own status: draft, scheduled, publishing, published or failed. A failed target carries an error with a code, a category and a source that says who can fix it, see Publishing errors. A published target carries platformPostId and platformUrl.

When a platform is rate limiting or down, the target shows failed with its error while FeedHorizon waits to try again (3 attempts in total, after 2 and 10 minutes). The post stays publishing during that time. Only when the last attempt fails, or the error is one that is not retried, does the target count as failed for good and post.target.failed is sent.

What you can do in each state

Calldraftscheduledpublishingpublishedpartially_failedfailed
PATCH /posts/{id} (edit)YesYesNoNoNoYes
POST /posts/{id}/publishYesYesNoNoNoYes
POST /posts/{id}/cancelNoYesNoNoNoNo
POST /posts/{id}/retryNoNoOnly failed targetsNoYesYes
POST /posts/{id}/duplicateYesYesYesYesYesYes
DELETE /posts/{id}YesYesNoYesYesYes
  • Edit is refused with 409 post_not_editable as soon as any account is publishing or published. To change the text of a post that is partly live, duplicate it.
  • Retry sends only the failed accounts again; published ones stay as they are. It answers 409 post_not_failed when no account has failed.
  • Cancel takes a scheduled post off the schedule and keeps it as a draft. On any other status it answers 409 post_not_scheduled.
  • Delete removes the post from FeedHorizon. Posts that are already live stay on the platforms. While an account is being sent, delete answers 409 post_publishing; try again a few seconds later.

Duplicate to change a live post

A post that is partly or fully live cannot be edited, because the live part could no longer match it. To post a corrected version, for example after platform_rejected on one account:

  1. POST /posts/{id}/duplicate creates a draft with the same text, media, accounts and own texts.
  2. PATCH the copy: keep only the accounts that failed in targets, and fix the text.
  3. Schedule or publish the copy.

Webhooks along the way

WhenEvent
A post gets a time (created scheduled, or a draft is scheduled)post.scheduled
Text, time, accounts or status changepost.updated
One account publishedpost.target.published
One account failed for goodpost.target.failed
All accounts donepost.published, post.partial or post.failed
The post was deletedpost.deleted

The payload of each event is in Webhook events.