---
title: "Create a post"
method: POST
path: "/posts"
tags: ["Posts"]
---

# Create a post

`POST /posts`

## Request

- Base URL: `https://api.post-quest.com/v1`
- URL: `https://api.post-quest.com/v1/posts`
- Auth: HTTP bearer

Requires `posts:write`. Creation defaults to a draft. Set `is_draft` to
`false` and provide an offset-aware `scheduled_at` to schedule. Immediate
publishing also requires `publish:now`, workspace opt-in, `is_draft: false`,
and `publish_now: true`.

## Headers

- `Idempotency-Key` string

## Request body

- CreatePostInput
  - `caption` string, required
  - `social_account_ids` string[]
  - `platform_captions` object: Platform or `platform:<social account id>` target keys mapped to custom captions.
  - `content_pillar` string, nullable
  - `content_pillar_id` string, uuid, nullable
  - `media_ids` string[]
  - `scheduled_at` string, date-time, nullable: Must contain `Z` or an explicit UTC offset and be in the future.
  - `publish_now` boolean
  - `platform_configurations` PlatformConfigurations: On updates, submitted fields are merged into the stored settings; omitted platforms and fields keep their values.
    - `tiktok` TikTokConfiguration
      - `title` string, nullable
      - `privacy_status` 'public' | 'private' | 'null', nullable
      - `allow_comment` boolean
      - `allow_duet` boolean
      - `allow_stitch` boolean
      - `is_ai_generated` boolean
      - `disclose_video_content` boolean
      - `disclose_your_brand` boolean
      - `disclose_branded_content` boolean
    - `youtube` YouTubeConfiguration
      - `title` string, nullable
      - `category_id` '1' | '2' | '10' | '15' | '17' | '19' | '20' | '22' | '23' | '24' | '25' | '26' | '27' | '28' | '29' | 'null', nullable
      - `visibility` 'public' | 'private' | 'unlisted' | 'null', nullable
      - `license` 'youtube' | 'creativeCommon' | 'null', nullable
      - `notify_subscribers` boolean
      - `allow_embedding` boolean
      - `made_for_kids` boolean
  - `account_configurations` AccountConfigurations: Keys use `pinterest:{social_account_id}`.
  - `is_draft` boolean: Set false before scheduling or publishing from this operation.

## Response `201`

Post created.

- PostResponse
  - `data` Post, required
    - `id` string, uuid, required
    - `workspace_id` string, uuid, required
    - `caption` string, required
    - `status` 'idea' | 'draft' | 'needs_improvement' | 'ready' | 'scheduled' | 'publishing' | 'published' | 'failed' | 'skipped' | 'archived', required
    - `content_pillar_id` string, uuid, nullable, required
    - `scheduled_at` string, date-time, nullable, required
    - `published_at` string, date-time, nullable, required
    - `timezone` string, required
    - `media_ids` string[], required
    - `targets` PostTarget[], required
      - `platform` 'instagram' | 'facebook' | 'x' | 'youtube' | 'tiktok' | 'pinterest' | 'linkedin' | 'threads' | 'bluesky' | 'mastodon', required
      - `social_account_id` string, uuid, nullable, required
      - `caption` string, required
      - `publish_status` 'published' | 'pending' | 'failed' | 'null', nullable, required
      - `external_url` string, uri, nullable, required
    - `platform_configurations` PlatformConfigurations, required: On updates, submitted fields are merged into the stored settings; omitted platforms and fields keep their values.
      - `tiktok` TikTokConfiguration
        - `title` string, nullable
        - `privacy_status` 'public' | 'private' | 'null', nullable
        - `allow_comment` boolean
        - `allow_duet` boolean
        - `allow_stitch` boolean
        - `is_ai_generated` boolean
        - `disclose_video_content` boolean
        - `disclose_your_brand` boolean
        - `disclose_branded_content` boolean
      - `youtube` YouTubeConfiguration
        - `title` string, nullable
        - `category_id` '1' | '2' | '10' | '15' | '17' | '19' | '20' | '22' | '23' | '24' | '25' | '26' | '27' | '28' | '29' | 'null', nullable
        - `visibility` 'public' | 'private' | 'unlisted' | 'null', nullable
        - `license` 'youtube' | 'creativeCommon' | 'null', nullable
        - `notify_subscribers` boolean
        - `allow_embedding` boolean
        - `made_for_kids` boolean
    - `validation` object, nullable, required
    - `updated_at` string, date-time, nullable, required

## Other responses

- `400`: Malformed request, invalid idempotency key, or credential in the query string.
- `401`: Missing, invalid, expired, revoked, or unbound API key.
- `402`: The workspace does not have effective paid REST access.
- `403`: The key lacks an ability, onboarding is incomplete, or publish-now is disabled.
- `409`: Resource state, idempotency payload, or in-progress idempotency conflict.
- `422`: Request fields, platform capability, media, schedule, or quota validation failed.
- `429`: The per-key global or media-specific request limit was exceeded.
- `500`: Unexpected server failure. Internal details are never exposed.

---

[API](https://skmtc.dev/post-quest/apis/postquest-public-api.md) · [All operations](https://skmtc.dev/post-quest/apis/postquest-public-api/llms.txt) · [OpenAPI document](https://skmtc.dev/post-quest/apis/postquest-public-api/revisions/089d3c362f35?raw)
