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

# Create a post

`POST /posts`

## Request

- Base URL: `https://www.postbase.so/api/v1`
- URL: `https://www.postbase.so/api/v1/posts`
- Auth: HTTP bearer

Save a draft, or schedule a post or thread. Send an Idempotency-Key so a retry can't post twice.

## Headers

- `Idempotency-Key` string

## Request body

- object
  - `body` string: The post text, for a single post.
  - `thread` string[]: Several posts to publish as a thread, in order. Takes precedence over body.
  - `channel_ids` string[]: Channels to publish to, from GET /channels.
  - `channel_bodies` object: Text for particular channels instead of body, keyed by channel id. Each is a single post.
  - `scheduled_at` string, date-time, nullable: When to publish: ISO 8601 with Z or an offset (2026-10-01T09:00:00+01:00). Omit or null to save a draft.
  - `schedule_in_minutes` number: Publish this many minutes from now, on the server's clock. Instead of scheduled_at.
  - `media_ids` string[]: Files from GET /media to attach, in order.
  - `media_urls` string[]: Public https links to images or a video, attached after media_ids. Each is downloaded into the media library (up to 10 per request, 200 MB each).
  - `youtube` object
    - `title` string
    - `privacy` 'public' | 'unlisted' | 'private'
    - `made_for_kids` boolean: Required to schedule to YouTube.
  - `idempotency_key` string: Same as the Idempotency-Key header.

## Response `200`

A repeat of an earlier request (same idempotency key)

- object
  - `post` CreatedPost
    - `id` string, uuid, required
    - `body` string
    - `scheduled_at` string, date-time, nullable
    - `status` 'draft' | 'scheduled' | 'publishing' | 'published' | 'failed', required
    - `media` integer: How many files are attached
    - `warning` string: Something to tell the user, such as X charging for links
    - `idempotent_replay` boolean: True when this repeats an earlier request with the same idempotency key

## Other responses

- `201`: Created
- `400`: Invalid request
- `401`: Missing or invalid API key
- `402`: No active plan
- `429`: Rate limited

---

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