---
title: "Create post — schedule or publish now"
method: POST
path: "/api/posts"
tags: ["Posts"]
---

# Create post — schedule or publish now

`POST /api/posts`

## Request

- Base URL: `https://www.fuxux.com`
- URL: `https://www.fuxux.com/api/posts`
- Auth: none declared

If `draft` is `true`, the post is stored with status `draft` and nothing is scheduled or published. Otherwise, if `scheduled_at` is set, variants are stored as scheduled and returned without publishing. If neither is set, the server attempts immediate publish to each platform in `captions`.

## Request body

- PostCreate: `captions` is required unless `draft` is `true`, in which case `prompt` or at least one caption must be present instead.
  - `prompt` string: Optional idea stored on the post
  - `captions` object, required: Map of platform id → caption. Platform ids: `twitter`, `instagram`, `linkedin`, `facebook`, `tiktok`, `youtube`, `bluesky`, `threads`, `pinterest`, `discord`, `kick`, `twitch`. Unknown platform keys are ignored. Without `targets`, each captioned platform posts to its first connected account. Reddit is not available through the API: Reddit posts are created in the Fuxux web app, and a `reddit` caption or target is refused with 403 `reddit_web_only`. Google Business Profile is coming soon and can't be connected or posted to yet.
  - `targets` PostTarget[]: Optional: exactly which connected accounts to post to, with per-platform options. Each target needs a caption for its platform in `captions`. Needed for picking between several accounts on one platform.
    - `account_id` string, uuid, required: Connected account id from `GET /api/accounts`
    - `platform` 'twitter' | 'instagram' | 'linkedin' | 'facebook' | 'tiktok' | 'youtube' | 'bluesky' | 'threads' | 'pinterest' | 'discord' | 'kick' | 'twitch', required: Must match the account's platform
    - `format` 'feed' | 'story': Instagram and Facebook only; defaults to `feed`
    - `boardId` string: Pinterest only: id of the board to pin to. If omitted, the pin goes to the account's first public board.
    - `tiktokOptions` object: TikTok only. `mode` `inbox` (default) sends the video to the creator's TikTok inbox to finish; `direct` publishes it (needs Direct Post access on the account).
      - `mode` 'inbox' | 'direct'
      - `privacyLevel` string: One of the privacy levels TikTok offers the account (for example `SELF_ONLY`)
      - `disableComment` boolean
      - `disableDuet` boolean
      - `disableStitch` boolean
      - `brandOrganic` boolean: Promotional content (your own brand)
      - `brandContent` boolean: Paid partnership (branded content); can't be private
    - `category` object: Twitch and Kick only: stream category set with the title (Twitch game id or Kick category id)
      - `id` string, required
      - `name` string, required
  - `scheduled_at` string, date-time: If set, post is scheduled (must be in the future). If omitted, the app publishes immediately. Mutually exclusive with `draft`.
  - `media_urls` string[]: Public URLs from `POST /api/media/upload`
  - `draft` boolean: If `true`, saves the post as a draft instead of scheduling or publishing it. `captions` is not required when `draft` is `true`, but `prompt` or at least one caption must be present. Mutually exclusive with `scheduled_at`.

## Response `200`

Draft saved, scheduled post, or publish outcome

- union
  - object
    - `post` object, required
      - `id` string, uuid, required
      - `status` 'draft', required
  - object
    - `post` object, required
      - `id` string, uuid, required
      - `status` 'scheduled', required
      - `scheduled_at` string, date-time, required
  - object
    - `post` object, required
      - `id` string, uuid, required
      - `status` 'published' | 'publishing' | 'failed', required: `publishing` means a platform is still processing: read `GET /api/posts/{id}` after a minute. `published` means at least one platform succeeded; check `results` for the rest.
    - `results` PublishResult[], required
      - `platform` string
      - `account_id` string, nullable
      - `account_label` string, nullable: Display label for the account, e.g. "@brand".
      - `success` boolean
      - `platform_post_id` string, nullable
      - `error` string, nullable
      - `still_processing` boolean: Some networks confirm publish status asynchronously. If true, `success` is false but the post was accepted and may still go live — check the post's status again shortly rather than treating this as a hard failure.
      - `inbox_pending` boolean: The platform accepted the media into an inbox/draft flow (e.g. TikTok's video upload inbox) rather than publishing directly. Counted as success, but the post is not necessarily live yet — the creator may need to finish posting from within that platform's own app.

## Other responses

- `400`: Validation error
- `401`: Unauthorized
- `403`: Refused; nothing was created. See `code`: `post_quota_reached` (the plan's post allowance for this month would be exceeded), `x_allowance` (the month's X allowance is used up) or `reddit_web_only` (Reddit can only be posted to from the web app).
- `429`: Too many requests
- `500`: Server error

---

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