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
| Status | Meaning |
|---|---|
draft | Saved without a time. Nothing happens until you schedule or publish it |
scheduled | Waiting for its time. publishNow and POST /posts/{id}/publish answer with scheduled too and start sending right away |
publishing | At least one account is being sent, or waits for an automatic retry |
published | Every account published |
partially_failed | Every account is done; some published, some failed |
failed | Every 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
| Call | draft | scheduled | publishing | published | partially_failed | failed |
|---|---|---|---|---|---|---|
PATCH /posts/{id} (edit) | Yes | Yes | No | No | No | Yes |
POST /posts/{id}/publish | Yes | Yes | No | No | No | Yes |
POST /posts/{id}/cancel | No | Yes | No | No | No | No |
POST /posts/{id}/retry | No | No | Only failed targets | No | Yes | Yes |
POST /posts/{id}/duplicate | Yes | Yes | Yes | Yes | Yes | Yes |
DELETE /posts/{id} | Yes | Yes | No | Yes | Yes | Yes |
- Edit is refused with
409 post_not_editableas 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_failedwhen 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:
POST /posts/{id}/duplicatecreates a draft with the same text, media, accounts and own texts.PATCHthe copy: keep only the accounts that failed intargets, and fix the text.- Schedule or publish the copy.
Webhooks along the way
| When | Event |
|---|---|
| A post gets a time (created scheduled, or a draft is scheduled) | post.scheduled |
| Text, time, accounts or status change | post.updated |
| One account published | post.target.published |
| One account failed for good | post.target.failed |
| All accounts done | post.published, post.partial or post.failed |
| The post was deleted | post.deleted |
The payload of each event is in Webhook events.