---
title: "Schedule or immediately publish one draft"
method: POST
path: "/posts/{postId}/schedule"
tags: ["Scheduling"]
---

# Schedule or immediately publish one draft

`POST /posts/{postId}/schedule`

## Request

- Base URL: `https://www.juzpost.com/api/cli/v1`
- URL: `https://www.juzpost.com/api/cli/v1/posts/{postId}/schedule`
- Auth: HTTP bearer

Fans one draft out to between one and ten social accounts. Supply `publishAt` to set a
future fire time, or omit it entirely to publish right now. A future time must be at
least five minutes and at most roughly six months out. The response reports one result
per account; check each entry rather than only the top-level `success`, because a
partial failure still returns `200`. Immediate publishing requires the `publish`
capability while a future time requires `schedule`; either way a plan that lacks it
returns `402`.

## Path parameters

- `postId` string, uuid, required

## Request body

- SchedulePostRequest: Which accounts to send one draft to, and when. Every key used in an overrides map must also appear in `socialAccountIds`, or the whole request is rejected with `400`.
  - `socialAccountIds` string[], required: The accounts to publish to, between one and ten. Duplicates are silently collapsed. If any id is not yours the entire request fails with `404` and does not partially schedule.
  - `publishAt` string, date-time: When to publish, as an ISO 8601 UTC instant. Must be at least 5 minutes and at most roughly 6 months in the future. Omit this field entirely to publish immediately, but that path needs the `publish` capability instead of `schedule`.
  - `title` string: Title to use for this run, overriding the stored one and persisted back onto the post. Note this limit is stricter than the 200 characters `POST /posts` accepts.
  - `description` string: Description to use for this run, overriding the stored one and persisted back onto the post. Also re-checked against each target platform's own caption limit.
  - `hashtags` string[]: Hashtags to use for this run, overriding the stored ones. Do not include the `#`.
  - `platformOverrides` object: Per-account content overrides, keyed by social account id. Every key must be one of the ids in `socialAccountIds`.
  - `publishAtOverrides` object: Per-account fire times, keyed by social account id, each an ISO 8601 UTC instant. Accounts not listed use the top-level `publishAt`. Every key must be one of the ids in `socialAccountIds`.
  - `tiktokSettings` object: Per-account TikTok settings, keyed by social account id. Every key must be one of the ids in `socialAccountIds`.
  - `pinterestSettings` object: Per-account Pinterest settings, keyed by social account id. Every key must be one of the ids in `socialAccountIds`.
  - `blueskySettings` object: Per-account Bluesky alt text and content warnings, keyed by social account id. Every key must be one of the ids in `socialAccountIds` and must name a Bluesky account.
  - `wordpressSettings` object: Per-account WordPress post settings for a `blog` post, keyed by social account id. Every key must be one of the ids in `socialAccountIds` and must name a WordPress account. Nothing reaches WordPress before the post fires.

## Response `200`

Timers created. Inspect `results` per account: a mix of scheduled and failed
targets is still reported here rather than as an error status.

- ScheduleResult: Per-account results for one post. Note this shape is passed through from the underlying scheduler and, unlike the errors in this API, is not wrapped in an envelope.
  - `success` boolean, required: True only when no account was left failed or pending. Partial failure still returns HTTP 200 with this set to false, so always inspect `results`.
  - `results` TargetResult[], required: One entry per requested account, in the order they were processed.
    - `socialAccountId` string, uuid, required: The account this result is about.
    - `platform` string, nullable, required: The account's platform id, e.g. `instagram`; null if the account was removed.
    - `username` string, nullable, required: The account's handle on that platform; null if unknown or the account was removed.
    - `status` string, required: The account's state after the call. `scheduled` means a timer was created, `failed` when it could not be, or an existing state such as `published` when the target was already handled and was deliberately left alone.
    - `error` string: Present only when this account failed; explains why.

## Other responses

- `400`: Invalid body, a fire time outside the allowed window, an override keyed by an account not in `socialAccountIds`, a non-text post with no media, a caption longer than the target platform allows, or `blueskySettings` for an account that is not on Bluesky, with an alt text count that differs from its files, or with labels on a text post. Also `wordpressSettings` for an account that is not on WordPress, a category name the site does not have (the error lists the site's categories), or `seo` for an account whose site does not let it write Yoast SEO fields.
- `401`: No bearer token was sent, or the token is unknown, revoked or malformed. Run the device login again to obtain a new token.
- `402`: The plan behind this token does not include the capability this operation needs. `error.details.requiredPlan` names the tier that does. This is never a token problem, so do not retry without changing the plan.
- `404`: The post does not exist, or at least one requested social account does not. Which one is deliberately not disclosed.
- `409`: The post left `draft` status before the timer could be claimed. It is already scheduled or uploading. Re-read the post before retrying.

---

[API](https://skmtc.dev/juzpost/apis/juzpost-rest-api.md) · [All operations](https://skmtc.dev/juzpost/apis/juzpost-rest-api/llms.txt) · [OpenAPI document](https://skmtc.dev/juzpost/apis/juzpost-rest-api/revisions/19296da24f95?raw)
