> ## Documentation Index
> Fetch the complete documentation index at: https://paragraph.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Update a post by ID

> Update an existing post in your publication. The publication is identified by the API key provided in the Authorization header.

**Behavior:**
- Only provided fields are updated; omitted fields remain unchanged
- When `markdown` is provided, it replaces the full content. Rich blocks (embeds, buttons, callouts) created in the editor will be lost — the markdown to editor conversion is lossy for blocks without a markdown equivalent
- Set `status` to `"published"` to publish a draft, `"draft"` to unpublish, or `"archived"` to archive
- When editing an already-live post that should remain live, include `status: "published"` in the update and verify the returned post status before telling the writer it is live
- Set `scheduledAt` (Unix timestamp in milliseconds) to schedule a draft's first-publish for a future time. Must be in the future and at most 30 days out. Only valid for posts that haven't been published or already scheduled. Pass `scheduledAt: null` to cancel a previously scheduled publish (or to reschedule: cancel first, then schedule again with the new time). Set `sendNewsletter: true` alongside `scheduledAt` to email subscribers when the post publishes.
- Set `imageUrl` to update the post's cover/hero image; the URL is fetched, re-hosted, and a placeholder is generated. Pass `clearImage: true` to remove the existing cover.



## OpenAPI

````yaml /paragraph-api/openapi.json put /v1/posts/{postId}
openapi: 3.1.0
info:
  title: Paragraph API
  version: 1.0.0
  description: >-
    Public API for interacting with Paragraph publications, posts, users, and
    coined writing.


    ## Rate Limiting

    API requests are rate-limited to ensure fair usage. Contact
    support@paragraph.com for higher limits.


    ## Pagination

    List endpoints support cursor-based pagination using `cursor` and `limit`
    parameters.
  contact:
    name: Paragraph Support
    email: support@paragraph.com
    url: https://paragraph.com/support
  license:
    name: MIT
    url: https://opensource.org/licenses/MIT
servers:
  - url: https://public.api.paragraph.com/api
    description: Production server
security:
  - {}
tags:
  - name: publications
    description: Operations related to publications
  - name: posts
    description: Operations related to posts and content
  - name: users
    description: Operations related to users and authors
  - name: coins
    description: Operations related to tokenized content
  - name: subscribers
    description: Operations related to subscriber management (requires API key)
paths:
  /v1/posts/{postId}:
    put:
      tags:
        - posts
      summary: Update a post by ID
      description: >-
        Update an existing post in your publication. The publication is
        identified by the API key provided in the Authorization header.


        **Behavior:**

        - Only provided fields are updated; omitted fields remain unchanged

        - When `markdown` is provided, it replaces the full content. Rich blocks
        (embeds, buttons, callouts) created in the editor will be lost — the
        markdown to editor conversion is lossy for blocks without a markdown
        equivalent

        - Set `status` to `"published"` to publish a draft, `"draft"` to
        unpublish, or `"archived"` to archive

        - When editing an already-live post that should remain live, include
        `status: "published"` in the update and verify the returned post status
        before telling the writer it is live

        - Set `scheduledAt` (Unix timestamp in milliseconds) to schedule a
        draft's first-publish for a future time. Must be in the future and at
        most 30 days out. Only valid for posts that haven't been published or
        already scheduled. Pass `scheduledAt: null` to cancel a previously
        scheduled publish (or to reschedule: cancel first, then schedule again
        with the new time). Set `sendNewsletter: true` alongside `scheduledAt`
        to email subscribers when the post publishes.

        - Set `imageUrl` to update the post's cover/hero image; the URL is
        fetched, re-hosted, and a placeholder is generated. Pass `clearImage:
        true` to remove the existing cover.
      operationId: updatePost
      parameters:
        - name: postId
          in: path
          required: true
          schema:
            type: string
          description: Unique identifier of the post to update
      requestBody:
        description: Body
        content:
          application/json:
            schema:
              type: object
              properties:
                markdown:
                  type: string
                  description: >-
                    Post content in Markdown format. Replaces the full body.
                    Markdown cannot represent buttons or linked images — if the
                    post has any, editing with `markdown` drops them. Use
                    `bodyJson` instead for those posts. Provide `markdown` OR
                    `bodyJson`, not both.
                bodyJson:
                  type: string
                  description: >-
                    Post content as a Tiptap document, JSON-stringified (e.g.
                    '{"type":"doc","content":[...]}'). Use this instead of
                    `markdown` when the body needs blocks markdown can't express
                    — Subscribe/Share/custom buttons or linked images — so they
                    are preserved. Replaces the full body and is validated
                    server-side; an invalid document is rejected with a
                    node-pathed error. Provide `markdown` OR `bodyJson`, not
                    both.
                title:
                  type: string
                  maxLength: 200
                  description: Title of the post
                subtitle:
                  type: string
                  maxLength: 300
                  description: Optional subtitle or brief summary
                slug:
                  type: string
                  minLength: 1
                  maxLength: 256
                  description: URL-friendly identifier for the post
                postPreview:
                  type: string
                  maxLength: 500
                  description: Preview text for the post
                categories:
                  oneOf:
                    - type: array
                      items:
                        type: string
                    - type: string
                  description: >-
                    Category tags for the post. Can also be a comma-separated
                    string.
                status:
                  type: string
                  enum:
                    - draft
                    - published
                    - archived
                  description: >-
                    Set to 'published' to publish a draft or keep an
                    already-live post published after edits, 'draft' to
                    unpublish, or 'archived' to archive
                scheduledAt:
                  description: >-
                    Unix timestamp (milliseconds) to schedule the post's first
                    publish at a future time. Must be in the future and at most
                    30 days out. Only valid for draft posts that haven't been
                    published or already scheduled. Cannot be combined with
                    status: 'draft' or 'archived'. Pass null to cancel a
                    previously scheduled publish. The value 0 is treated the
                    same as omitting the field (no scheduling request); note
                    that on an already-scheduled post, omitting `scheduledAt`
                    while changing `status` cancels the schedule.
                  type:
                    - integer
                    - 'null'
                  minimum: 0
                sendNewsletter:
                  oneOf:
                    - type: boolean
                    - type: string
                      enum:
                        - 'true'
                        - 'false'
                        - '1'
                        - '0'
                  description: >-
                    Whether to send an email newsletter to subscribers when the
                    post publishes. Only meaningful when publishing (status:
                    'published') or scheduling (scheduledAt set). Default: false
                publishedAt:
                  type: integer
                  minimum: 0
                  exclusiveMinimum: 0
                  description: >-
                    Unix timestamp (milliseconds) to set as the post's publish
                    date. Once set, the date is preserved across re-publishes.
                imageUrl:
                  type: string
                  format: uri
                  description: >-
                    URL of an image to set as the post's cover/hero image. The
                    image is fetched, re-hosted on Paragraph's CDN, and a
                    placeholder is generated. Pass clearImage: true instead to
                    remove the existing cover.
                clearImage:
                  type: boolean
                  description: >-
                    When true, removes the post's existing cover/hero image.
                    Ignored if imageUrl is also provided.
      responses:
        '200':
          description: Post updated successfully
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                    enum:
                      - true
                    description: Whether the update succeeded
                required:
                  - success
        '400':
          description: Invalid request - check field values
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                    enum:
                      - false
                    description: Always false for error responses
                  msg:
                    type: string
                    description: Human-readable error message
                required:
                  - success
                  - msg
        '401':
          description: Invalid or missing API key
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                    enum:
                      - false
                    description: Always false for error responses
                  msg:
                    type: string
                    description: Human-readable error message
                required:
                  - success
                  - msg
        '404':
          description: Post not found in your publication
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                    enum:
                      - false
                    description: Always false for error responses
                  msg:
                    type: string
                    description: Human-readable error message
                required:
                  - success
                  - msg
        '409':
          description: >-
            Conflict - the post was edited in the writer's editor after the
            revision you based this edit on. Re-read the current version and
            re-apply your change.
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                    enum:
                      - false
                    description: Always false for error responses
                  msg:
                    type: string
                    description: Human-readable error message
                required:
                  - success
                  - msg
        '500':
          description: Internal server error
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                    enum:
                      - false
                    description: Always false for error responses
                  msg:
                    type: string
                    description: Human-readable error message
                required:
                  - success
                  - msg
      security:
        - apiKey: []
      x-codeSamples:
        - lang: typescript
          label: Update a post
          source: |-
            import { ParagraphAPI } from "@paragraph-com/sdk"

            const api = new ParagraphAPI({ apiKey: "your-api-key" })
            await api.posts.update({
              id: "3T2PQZlsdQtigUp4fhlb",
              title: "Updated Title",
              markdown: "## New content\n\nUpdated post body.",
              status: "published"
            })
        - lang: typescript
          label: Schedule a draft for a future publish
          source: |-
            import { ParagraphAPI } from "@paragraph-com/sdk"

            const api = new ParagraphAPI({ apiKey: "your-api-key" })
            await api.posts.update({
              id: "3T2PQZlsdQtigUp4fhlb",
              scheduledAt: Date.now() + 24 * 60 * 60 * 1000,
            })
        - lang: typescript
          label: Cancel a scheduled publish
          source: |-
            import { ParagraphAPI } from "@paragraph-com/sdk"

            const api = new ParagraphAPI({ apiKey: "your-api-key" })
            await api.posts.update({
              id: "3T2PQZlsdQtigUp4fhlb",
              scheduledAt: null,
            })
        - lang: bash
          label: Update post using curl
          source: >-
            curl -X PUT
            "https://public.api.paragraph.com/api/v1/posts/3T2PQZlsdQtigUp4fhlb"
            \
              -H "Authorization: Bearer your-api-key" \
              -H "Content-Type: application/json" \
              -d '{"title": "Updated Title", "markdown": "New content"}'
components:
  securitySchemes:
    apiKey:
      type: http
      scheme: bearer
      description: >-
        API key for authenticating protected endpoints. Pass as Bearer token in
        Authorization header.

````