Docs

Handle failed posts

React to failed accounts with webhooks, tell apart what you can fix from what fixes itself, and retry.

A post can fail on one account and succeed on the others. This recipe listens for failures per account, decides from the error who has to act, and retries once the cause is gone.

1. Listen for failures

Create a webhook for the events that matter here:

curl -X POST https://feedhorizon.com/api/v1/webhooks \
  -H "Authorization: Bearer $FEEDHORIZON_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Failures",
    "url": "https://api.example.com/webhooks/feedhorizon",
    "events": ["post.target.failed", "account.needs_reauth", "account.expiring"]
  }'

post.target.failed arrives once per account that failed for good: after FeedHorizon's own retries, or at once for errors that will not go away by trying again.

2. Decide who acts

Every failure carries an error with a code, a category and a source. source tells you who can fix it:

sourceWho actsTypical codes
userYou or your customeraccount_needs_reauth, platform_auth_failed, platform_rejected
platformNobody; the platform was busy or down and FeedHorizon tried againplatform_rate_limited, platform_unavailable
systemCheck, then retry or contact supporttimeout, publish_failed
app.post('/webhooks/feedhorizon', express.raw({ type: 'application/json' }), async (req, res) => {
    if (!verifyFeedHorizonSignature(req.body.toString(), req.get('X-Webhook-Signature'), process.env.FEEDHORIZON_WEBHOOK_SECRET)) {
        return res.sendStatus(401);
    }
    res.sendStatus(200); // answer fast, work afterwards

    const { event, data } = JSON.parse(req.body);
    if (event !== 'post.target.failed') return;

    switch (data.error.category) {
        case 'auth_expired':
            // The account must be connected again: send the customer a connect link.
            return askToReconnect(data.profileId, data.accountId, data.platform);
        case 'rejected':
            // The platform refused this content: show the message to whoever wrote it.
            return notifyAuthor(data.postId, data.platform, data.error.message);
        default:
            // Rate limits, outages, timeouts: log it and alert if it keeps happening.
            return logFailure(data);
    }
});

verifyFeedHorizonSignature and verify_signature are on the Webhooks page. Every code with what to do is in Publishing errors.

3. Retry

Once the cause is fixed (the account is connected again, the platform is back), send the failed accounts again:

curl -X POST https://feedhorizon.com/api/v1/posts/post_…/retry \
  -H "Authorization: Bearer $FEEDHORIZON_API_KEY"

Only the failed accounts are sent; accounts that already published stay as they are.

  • After account_needs_reauth or platform_auth_failed, wait for account.connected for that account, then retry the posts that failed on it.
  • After platform_rejected, retrying the same text fails the same way. Change the post first. If other accounts already published, the post can no longer be edited: duplicate it, keep only the failed account and fix the text.
  • After timeout, look at the account on the platform first. The post may have gone live even though the platform did not confirm it in time; a retry would post it twice.

4. Prevent the next failure

  • Run POST /posts/validate before creating posts. It catches text that is too long, media a platform does not take, and accounts that need a reconnect (warning account_not_active).
  • React to account.expiring: the connection ends in 7 days. A new connect link before then avoids failures.
  • Spread many posts to the same account over time; platforms limit how often one account may post.