> ## 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.

# Create a draft

> Save a finished piece of short-form content — an X post or thread, a LinkedIn post, a one-off email, or an X Article — to your publication's library.

**What this does:**
- The piece is saved as a draft and shows up in the Paragraph app under Content, where you can edit it and send it.
- Nothing is posted, emailed, or scheduled. Sending happens in the app, so a draft you upload can't go out without you.
- Long-form Paragraph posts are a different resource — use `POST /v1/posts` for those.

**The body:**
- `body` carries the artifact itself, in the shape its kind uses (see the field descriptions below).
- It's validated the same way the Paragraph app validates it, so an X thread over 280 characters an entry, or an Article missing its headline, comes back with the same explanation you'd see in the app.
- Drafts created here are text-only. Media has to be uploaded to X or LinkedIn first, which the API can't do yet.



## OpenAPI

````yaml /paragraph-api/openapi.json post /v1/content
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/content:
    post:
      tags:
        - content
      summary: Create a draft
      description: >-
        Save a finished piece of short-form content — an X post or thread, a
        LinkedIn post, a one-off email, or an X Article — to your publication's
        library.


        **What this does:**

        - The piece is saved as a draft and shows up in the Paragraph app under
        Content, where you can edit it and send it.

        - Nothing is posted, emailed, or scheduled. Sending happens in the app,
        so a draft you upload can't go out without you.

        - Long-form Paragraph posts are a different resource — use `POST
        /v1/posts` for those.


        **The body:**

        - `body` carries the artifact itself, in the shape its kind uses (see
        the field descriptions below).

        - It's validated the same way the Paragraph app validates it, so an X
        thread over 280 characters an entry, or an Article missing its headline,
        comes back with the same explanation you'd see in the app.

        - Drafts created here are text-only. Media has to be uploaded to X or
        LinkedIn first, which the API can't do yet.
      operationId: createContent
      parameters: []
      requestBody:
        description: Body
        content:
          application/json:
            schema:
              type: object
              properties:
                kind:
                  type: string
                  enum:
                    - tweet
                    - linkedin
                    - newsletter
                    - x_article
                  description: What kind of piece this is
                title:
                  type: string
                  minLength: 1
                  maxLength: 200
                  description: >-
                    What this piece is called in your library. Sentence case, no
                    trailing period. Not published anywhere — for an X Article
                    headline, use `body.title`.
                body:
                  type: object
                  properties:
                    text:
                      type: string
                      description: >-
                        The post's text. `tweet`: a single tweet, at most 280
                        characters — use `tweets` for a thread and never send
                        both. `linkedin`: the post body.
                    tweets:
                      type: array
                      items:
                        type: string
                      description: >-
                        `tweet` only. One entry per tweet, in posting order,
                        each at most 280 characters. Never concatenate a thread
                        into one entry.
                    subject:
                      type: string
                      description: '`newsletter` only. Subject line.'
                    preheader:
                      type: string
                      description: >-
                        `newsletter` only. Optional preview line shown after the
                        subject.
                    body:
                      type: string
                      description: >-
                        `newsletter`: the email body. `x_article`: the article's
                        full CommonMark markdown.
                    title:
                      type: string
                      description: >-
                        `x_article` only. The headline as published on X.
                        Separate from the piece's `title`, which only names it
                        in your library.
                    canonicalUrl:
                      type: string
                      description: >-
                        `x_article` only. The original post this Article is a
                        version of. It must also appear as a markdown link
                        inside `body`.
                    media:
                      readOnly: true
                      description: >-
                        Not accepted. Media has to be uploaded to the
                        destination platform first, which the API can't do yet;
                        sending this field is rejected.
                  additionalProperties: false
                  description: The artifact itself, in the shape this kind uses
              required:
                - kind
                - title
                - body
      responses:
        '200':
          description: Draft created successfully
          content:
            application/json:
              schema:
                type: object
                properties:
                  id:
                    type: string
                    description: Unique identifier for this piece of content
                  kind:
                    type: string
                    description: >-
                      What this piece is: `tweet`, `linkedin`, `newsletter`, or
                      `x_article`
                  title:
                    type: string
                    description: What this piece is called in your library
                  excerpt:
                    type: string
                    description: First readable line of the body, for listing views
                  status:
                    type: string
                    enum:
                      - draft
                      - published
                      - archived
                    description: >-
                      Whether this piece has been delivered, is still a draft,
                      or was archived
                  scheduled:
                    type: boolean
                    description: Whether a scheduled send is queued against this piece
                  lockedReason:
                    type:
                      - string
                      - 'null'
                    description: >-
                      Why this piece can't be edited right now, or null when it
                      can. A queued or in-flight send locks the words, because
                      they go out exactly as written.
                  publishedAt:
                    type:
                      - string
                      - 'null'
                    description: ISO 8601 timestamp of the first delivery, or null
                  url:
                    type:
                      - string
                      - 'null'
                    description: >-
                      Where this piece went live, from the same delivery
                      `publishedAt` came from. Null when it hasn't been
                      delivered, and null by design for a channel that publishes
                      no page: a custom email renders into the message itself,
                      so there is no address to link to. Never guessed — a
                      delivery whose id isn't shaped like its channel reports
                      null rather than a link that would 404.
                  archivedAt:
                    type:
                      - string
                      - 'null'
                    description: >-
                      ISO 8601 timestamp of when this piece was archived, or
                      null
                  createdAt:
                    type: string
                    description: ISO 8601 timestamp of creation
                  updatedAt:
                    type: string
                    description: ISO 8601 timestamp of the last change
                  body:
                    type: object
                    additionalProperties: {}
                    description: The artifact itself, in the shape its kind uses
                required:
                  - id
                  - kind
                  - title
                  - excerpt
                  - status
                  - scheduled
                  - lockedReason
                  - publishedAt
                  - url
                  - archivedAt
                  - createdAt
                  - updatedAt
                  - body
        '400':
          description: The draft is missing content or doesn't match its kind
          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: Publication not found
          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: Draft an X thread
          source: |-
            import { ParagraphAPI } from "@paragraph-com/sdk"

            const api = new ParagraphAPI({ apiKey: "your-api-key" })
            const draft = await api.content.create({
              kind: "tweet",
              title: "Thread on writing in public",
              body: { tweets: ["Writing in public changes what you write.", "Here's what changed for me."] },
            })
        - lang: typescript
          label: Draft a newsletter
          source: |-
            import { ParagraphAPI } from "@paragraph-com/sdk"

            const api = new ParagraphAPI({ apiKey: "your-api-key" })
            const draft = await api.content.create({
              kind: "newsletter",
              title: "October update",
              body: { subject: "What we shipped in October", body: "Hi everyone," },
            })
        - lang: bash
          label: Draft a LinkedIn post using curl
          source: |-
            curl -X POST "https://public.api.paragraph.com/api/v1/content" \
              -H "Authorization: Bearer your-api-key" \
              -H "Content-Type: application/json" \
              -d '{"kind":"linkedin","title":"Launch note","body":{"text":"We shipped it."}}'
components:
  securitySchemes:
    apiKey:
      type: http
      scheme: bearer
      description: >-
        API key for authenticating protected endpoints. Pass as Bearer token in
        Authorization header.

````