Guide

Publishing posts: validate, legs, partial success, retry

POST /api/v1/posts creates a multi-network job with one leg per platform. Status can be processing, succeeded, partial, or failed. Charge is per publish_leg. Retry only failed legs with POST /api/v1/posts/{id}/retry. Always send Idempotency-Key on create.

← GuidesPublishingUpdated 2026-08-10

In short

POST /api/v1/posts creates a multi-network job with one leg per platform. Status can be processing, succeeded, partial, or failed. Charge is per publish_leg. Retry only failed legs with POST /api/v1/posts/{id}/retry. Always send Idempotency-Key on create.

Request shape

Body includes text, platforms[] (facebook | instagram | linkedin | bluesky | mastodon), optional mediaUrls[] (HTTPS), optional scheduleAt (UTC), and platformOptions for network-specific fields.

Example bodyjson
{
  "text": "Summer hours start Monday.",
  "platforms": ["facebook", "linkedin", "bluesky"],
  "mediaUrls": ["https://cdn.example.com/promo.jpg"],
  "scheduleAt": null
}

Validate first

POST /api/v1/posts/validate costs 1 token and returns per-network valid/errors plus a tokensEstimate. Use it in composer UIs before spending publish tokens.

Legs and status machine

Each network is a leg with status pending, publishing, succeeded, failed, or skipped. Post status aggregates legs: succeeded (all good), partial (mix), failed (all failed), scheduled, processing.

  • partial is normal when one network rejects media or quota
  • Inspect leg.error.code and message for user-facing fixes
  • retryAvailable on a leg indicates retry is appropriate

Retry

POST /api/v1/posts/{id}/retry with optional platforms[] re-attempts failed legs only. Each attempt costs posts.retry_leg (10 tokens).

Token math

Immediate publish ≈ 10 × number of platforms (+ media.validate if used). Schedule adds 2 when the post is stored; legs charge when the timer fires.