# Distribution (/docs/social/distribution)



The `process-due` command runs once per minute (cron `* * * * *`) via
the `social-distribution-publish-due` workflow, provided there are
ready posts in the next 60 minutes.

For each due `scheduled_posts` row it:

1. Looks up the row (must have `scheduled_at <= now()` and a publishable
   status).
2. Resolves and refreshes the connected account's token via
   `SocialAccountTokenService`.
3. Calls the platform's publish API — Instagram Graph API or TikTok
   Content Posting API.
4. Updates the row's `status` and records the platform IDs.

## Status values [#status-values]

`scheduled_posts.status` takes one of these values:

| Status           | Meaning                                                                                             |
| ---------------- | --------------------------------------------------------------------------------------------------- |
| `pending`        | Slot reserved, waiting on content to attach.                                                        |
| `pending_assets` | Content attached, assets still generating.                                                          |
| `ready`          | Asset ready; will be picked up by `process-due`.                                                    |
| `draft`          | TikTok-only: pushed to the creator's TikTok drafts inbox.                                           |
| `posting`        | Publish call in progress.                                                                           |
| `posted`         | Successfully published.                                                                             |
| `failed`         | Publish call failed permanently (retries exhausted).                                                |
| `pending_manual` | Needs manual action — either `distributionMode = manual` or automatic publish failed and fell back. |

## Retries [#retries]

Each publish call has an inline retry loop: up to 3 attempts on HTTP
5xx responses with a short backoff (\~2–6 seconds total). A permanent
publisher failure moves the row to `pending_manual` so you can retry
from the UI. There is no multi-minute exponential backoff.

`recover-overdue` re-slots any `ready`/`failed` posts that missed their
window, running every 5 minutes.

## Manual mode publishing [#manual-mode-publishing]

* **Instagram** `posting_mode != 'automatic'` — the post stays in
  `pending_manual` waiting for you to approve/publish it.
* **TikTok** `posting_mode != 'automatic'` (default) — at slot time
  Layers pushes the asset to the creator's **TikTok drafts inbox** and
  marks the row `draft`. Finish the post from inside the TikTok app.

## Cross-posting [#cross-posting]

Each Social Distribution layer instance is bound to one connected
social account. To cross-post to another platform, install a second
Social Distribution layer instance wired to that account.

## Watermarks [#watermarks]

Layers does not add watermarks. AI-disclosure text, if required, should
be in your caption template or banned-phrase config.

## Republishing [#republishing]

If a post lands in `pending_manual` or `failed`, re-slot it from the
scheduled-posts UI. `recover-overdue` also handles this automatically
on its 5-minute tick.
