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

# Create a new post

`POST /v1/posts`

Create a new post in your publication. The publication is identified by the API key provided in the Authorization header.

**Requirements:**
- `title` field is required
- Provide content as either `markdown` (converted to TipTap JSON) OR `bodyJson` (a Tiptap document for content with buttons/linked images) — exactly one is required, not both

**Behavior:**
- The post will be created as published by default. Set `status` to `"draft"` to create a draft instead
- If `sendNewsletter` is true, an email will be sent to all subscribers when the post publishes
- Set `scheduledAt` (Unix timestamp in milliseconds) to schedule first-publish for a future time. Must be in the future and at most 30 days out. Scheduling cannot be combined with `status: "draft"`. When scheduled, the response `status` is `"scheduled"` and the post publishes (plus sends newsletter, if requested) at the scheduled time.

## Request body

- object
  - `markdown` string — Post content in Markdown format. Provide `markdown` OR `bodyJson`, not both. Markdown cannot represent buttons or linked images — use `bodyJson` for those.
  - `bodyJson` string — Post content as a Tiptap document, JSON-stringified (e.g. '{"type":"doc","content":[...]}'). Use instead of `markdown` when the body needs Subscribe/Share/custom buttons or linked images. Validated server-side; an invalid document is rejected. Provide `markdown` OR `bodyJson`, not both.
  - `title` string, required — Title of the post
  - `subtitle` string — Optional subtitle or brief summary
  - `imageUrl` string, uri — Optional URL to the post's cover image
  - `sendNewsletter` union — Whether to send an email newsletter to subscribers. Default: false
    - boolean
    - 'true' | 'false' | '1' | '0'
  - `status` 'published' | 'draft' — Status of the post. Default: published
  - `slug` string — Optional URL-friendly identifier for the post. If not provided, will be generated from title
  - `postPreview` string — Optional preview text for the post. If not provided, will be generated from content
  - `categories` union — Optional array of category tags for the post. Can also be a comma-separated string.
    - string[]
    - string
  - `authorIds` string[] — Optional user ids to credit as the post's authors, in byline order. Each id must be the publication's owner or an active team member — ids from outside the publication are rejected. Defaults to the API key's own user.
  - `scheduledAt` integer — Optional Unix timestamp (milliseconds) to schedule first-publish of the post at a future time. Must be in the future. Cannot be combined with status: 'draft'. When set, the post is created and queued to publish (and send newsletter, if requested) at the specified time. Pass 0 or omit the field for an unscheduled post.

## Response `200`

Post created successfully

- object
  - `id` string, required — The ID of the created post
  - `status` 'published' | 'draft' | 'scheduled', required — Final status of the post: 'published' if published immediately, 'draft' if created as a draft, 'scheduled' if queued to publish at scheduledAt

## Other responses

- `400` — Invalid request - check required fields
- `401` — Invalid or missing API key
- `404` — Publication not found
- `500` — Internal server error

---

[API](https://skmtc.net/paragraph-xyz/apis/paragraph-api.md) · [All operations](https://skmtc.net/paragraph-xyz/apis/paragraph-api/llms.txt) · [OpenAPI document](https://skmtc-service-staging.skmtc.workers.dev/v1/apis/paragraph-xyz/paragraph-api/versions/7bbf1b62c1a0/schema)
