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

# Create a draft or scheduled post

> Creates a post: a draft when `scheduled_for` is omitted, a scheduled
post otherwise. Main account only in v1. Supports the
`Idempotency-Key` header for safe retries (see the Idempotency guide).
Successful creation returns `201`.

Images attach per part: `parts[].media` is an array of
`{ object_key, alt_text? }` items, with `object_key` from
`POST /v1/media` (uploaded bytes required first). Up to 4 images or
exactly 1 GIF per part; `alt_text` is capped at 1,000 characters.
Video is not supported yet.

Advanced settings (`auto_retweet`, `auto_delete`, `auto_plug`,
`super_followers_only`): omit a setting to inherit its Default Post
Settings value from the SuperX app, send an object (or `true`/`false`
for `super_followers_only`) to override, or send `null` to turn it
off for this post. Exactly five settings inherit this way: auto
retweet, auto delete, auto plug, auto DM, and Super Followers only.
Other composer defaults (for example Bluesky cross-posting or
share-with-followers) are never applied to API posts. Auto DM always
inherits and has no request parameter; when a plan limit strips it,
the response carries `auto_dm_skipped: true` instead of failing.




## OpenAPI

````yaml /api-reference/openapi.yaml post /v1/scheduled-posts
openapi: 3.1.0
info:
  title: SuperX API
  version: 1.0.0
  description: >
    The SuperX public API: your Twitter/X content, analytics, audience and

    scheduling data over REST.


    All endpoints require an API key (`Authorization: Bearer sxk_...`) except

    `GET /v1/docs`. Keys are created in the SuperX app under Account > API / MCP
    / CLI

    and are server-side secrets.


    Timestamps are UTC ISO-8601 in both directions; inputs must carry an
    explicit

    `Z` or numeric offset. Every authenticated response carries

    `X-RateLimit-Limit`, `X-RateLimit-Remaining` and `X-RateLimit-Reset`
    headers.
  contact:
    name: SuperX
    url: https://superx.so
servers:
  - url: https://api.superx.so
security:
  - apiKey: []
tags:
  - name: Identity
  - name: Content
  - name: Analytics
  - name: Inspiration
  - name: Audience
  - name: Contact Lists
  - name: Signals
  - name: Media
  - name: Scheduling
  - name: Tags
  - name: Context
  - name: Queue
  - name: Articles
  - name: Meta
paths:
  /v1/scheduled-posts:
    post:
      tags:
        - Scheduling
      summary: Create a draft or scheduled post
      description: |
        Creates a post: a draft when `scheduled_for` is omitted, a scheduled
        post otherwise. Main account only in v1. Supports the
        `Idempotency-Key` header for safe retries (see the Idempotency guide).
        Successful creation returns `201`.

        Images attach per part: `parts[].media` is an array of
        `{ object_key, alt_text? }` items, with `object_key` from
        `POST /v1/media` (uploaded bytes required first). Up to 4 images or
        exactly 1 GIF per part; `alt_text` is capped at 1,000 characters.
        Video is not supported yet.

        Advanced settings (`auto_retweet`, `auto_delete`, `auto_plug`,
        `super_followers_only`): omit a setting to inherit its Default Post
        Settings value from the SuperX app, send an object (or `true`/`false`
        for `super_followers_only`) to override, or send `null` to turn it
        off for this post. Exactly five settings inherit this way: auto
        retweet, auto delete, auto plug, auto DM, and Super Followers only.
        Other composer defaults (for example Bluesky cross-posting or
        share-with-followers) are never applied to API posts. Auto DM always
        inherits and has no request parameter; when a plan limit strips it,
        the response carries `auto_dm_skipped: true` instead of failing.
      operationId: createScheduledPost
      parameters:
        - name: Idempotency-Key
          in: header
          required: false
          description: >-
            Unique key (max 64 characters) for safe retries. Replays carry the
            "Idempotency-Replayed" response header set to "true". Keys are
            retained for 24 hours.
          schema:
            type: string
            maxLength: 64
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                text:
                  type: string
                  description: >-
                    The post text (single post). Provide either `text` or
                    `parts`.
                parts:
                  type: array
                  description: >-
                    Thread parts, 1 to 25 items. Total text across parts is
                    limited to 25,000 characters.
                  items:
                    type: object
                    required:
                      - text
                    properties:
                      text:
                        type: string
                      media:
                        type: array
                        maxItems: 4
                        description: >-
                          Images for this part (up to 4, or exactly 1 GIF).
                          `object_key` from `POST /v1/media`.
                        items:
                          type: object
                          required:
                            - object_key
                          properties:
                            object_key:
                              type: string
                            alt_text:
                              type: string
                              maxLength: 1000
                              description: >-
                                Accessibility description delivered to X with
                                the image.
                scheduled_for:
                  type: string
                  format: date-time
                  description: >-
                    UTC ISO-8601 with explicit Z or offset. At least 60 seconds
                    in the future, at most 18 months out. Omit to create a
                    draft.
                title:
                  type: string
                  maxLength: 300
                  description: >-
                    Draft title shown in the SuperX app. Organizational only,
                    never posted.
                scratchpad:
                  type: string
                  maxLength: 30000
                  description: Private working notes attached to the post. Never posted.
                tags:
                  type: array
                  maxItems: 20
                  description: >-
                    Tag ids to assign (from `GET /v1/tags`). Unknown ids fail
                    the whole request with `400 unknown_tag` before anything is
                    created.
                  items:
                    type: string
                auto_retweet:
                  type: object
                  nullable: true
                  description: >-
                    Auto retweet. Omit to inherit your Default Post Settings;
                    `null` turns it off for this post.
                  required:
                    - after_hours
                  properties:
                    after_hours:
                      type: integer
                      minimum: 1
                      maximum: 12
                      description: Retweet the post this many hours after it goes live.
                    remove_after_hours:
                      type: integer
                      minimum: 1
                      maximum: 12
                      description: >-
                        Remove the retweet this many hours later. Omit to keep
                        it.
                auto_delete:
                  type: object
                  nullable: true
                  description: >-
                    Auto delete underperforming posts. Omit to inherit your
                    defaults; `null` turns it off for this post.
                  required:
                    - after_hours
                  properties:
                    after_hours:
                      type: integer
                      minimum: 1
                      maximum: 12
                      description: >-
                        Delete the post this many hours after it goes live if it
                        is under the views threshold.
                    threshold:
                      type: integer
                      minimum: 0
                      description: Views threshold (default 1000).
                auto_plug:
                  type: object
                  nullable: true
                  description: >-
                    Auto plug: reply with a template once the post hits a likes
                    threshold. Omit to inherit your defaults; `null` turns it
                    off for this post. Unknown template ids fail with `400
                    unknown_plug_template`.
                  required:
                    - template_id
                    - threshold
                  properties:
                    template_id:
                      type: string
                      description: Plug template id (from `GET /v1/plug-templates`).
                    threshold:
                      type: integer
                      minimum: 1
                      description: Likes threshold that triggers the plug reply.
                super_followers_only:
                  type: boolean
                  description: Post to Super Followers only. Omit to inherit your defaults.
                account_id:
                  type: string
                  description: >-
                    Must be your main account (or omitted). Linked accounts
                    return `403 writes_main_account_only`.
            examples:
              single:
                summary: One scheduled post
                value:
                  text: Shipping day.
                  scheduled_for: '2026-07-08T15:00:00Z'
              thread:
                summary: A thread draft
                value:
                  parts:
                    - text: 'Why most scheduling tools get threads wrong:'
                    - text: >-
                        They treat a thread as one blob of text instead of
                        parts.
              organized:
                summary: A draft with title and tags
                value:
                  text: Rough cut of the launch teaser.
                  title: Launch teaser v1
                  tags:
                    - V1StGXR8_Z5jdHi6B-myT
              with_image:
                summary: A scheduled post with an image
                value:
                  parts:
                    - text: Chart of the week.
                      media:
                        - object_key: u123/api_1751980800000_9f3a1c2b_chart.png
                          alt_text: Line chart of weekly revenue trending up
                  scheduled_for: '2026-07-08T15:00:00Z'
              advanced:
                summary: Explicit advanced settings
                value:
                  text: Shipping day.
                  scheduled_for: '2026-07-08T15:00:00Z'
                  auto_retweet:
                    after_hours: 6
                    remove_after_hours: 4
                  auto_plug:
                    template_id: tpl_abc123
                    threshold: 50
                  auto_delete: null
      responses:
        '201':
          description: >-
            The created post (echo of the accepted request, not the stored row).
            Replayed idempotent requests also return this body with the
            "Idempotency-Replayed" header set to "true". Applied advanced
            settings, inherited or explicit, are NOT echoed here; read them back
            via GET /v1/scheduled-posts.
          headers:
            Idempotency-Replayed:
              description: >-
                Present and "true" when this response was replayed from a
                previous request with the same Idempotency-Key.
              schema:
                type: string
            X-RateLimit-Limit:
              $ref: '#/components/headers/X-RateLimit-Limit'
            X-RateLimit-Remaining:
              $ref: '#/components/headers/X-RateLimit-Remaining'
            X-RateLimit-Reset:
              $ref: '#/components/headers/X-RateLimit-Reset'
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: string
                      status:
                        type: string
                        enum:
                          - draft
                          - scheduled
                      scheduled_for:
                        type: string
                        format: date-time
                        nullable: true
                      parts:
                        type: array
                        items:
                          type: object
                          properties:
                            text:
                              type: string
                            media:
                              type: array
                              description: Present only when the part carries media.
                              items:
                                type: object
                                properties:
                                  object_key:
                                    type: string
                                  url:
                                    type: string
                                  file_type:
                                    type: string
                                  size:
                                    type: integer
                                    nullable: true
                                  alt_text:
                                    type: string
                                    nullable: true
                      title:
                        type: string
                        nullable: true
                      scratchpad:
                        type: string
                        nullable: true
                      tags:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: string
                            name:
                              type: string
                            color:
                              type: string
                      created_at:
                        type: string
                        format: date-time
                      auto_dm_skipped:
                        type: boolean
                        description: >-
                          Present (and true) only when a plan limit stripped the
                          inherited Auto DM from this post. Absent otherwise.
              example:
                data:
                  id: V1StGXR8_Z5jdHi6B-myT
                  status: scheduled
                  scheduled_for: '2026-07-08T15:00:00.000Z'
                  parts:
                    - text: Shipping day.
                  title: null
                  scratchpad: null
                  tags: []
                  created_at: '2026-07-06T10:00:00.000Z'
        '400':
          description: >-
            Invalid parameter, invalid request, unknown tag id (`unknown_tag`),
            unknown plug template id (`unknown_plug_template`), or a media
            problem: unknown or foreign `object_key` (`invalid_media`), bytes
            never uploaded (`media_not_uploaded`), not a supported image
            (`unsupported_media_type`), or over the size cap
            (`media_too_large`).
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorEnvelope'
              example:
                error:
                  code: invalid_media
                  message: >-
                    Unknown object_key: u123/api_..._chart.png. Upload media
                    first via POST /v1/media.
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          description: |
            Read-only key (`insufficient_scope`), linked account
            (`writes_main_account_only`), onboarding not finished
            (`onboarding_required`), post quota used up
            (`post_quota_exceeded`), or a lapsed subscription (legacy string
            envelope).
          content:
            application/json:
              schema:
                oneOf:
                  - $ref: '#/components/schemas/ErrorEnvelope'
                  - $ref: '#/components/schemas/LegacyErrorEnvelope'
              example:
                error:
                  code: writes_main_account_only
                  message: The API can only create posts for your main account for now.
        '404':
          $ref: '#/components/responses/AccountNotFound'
        '409':
          description: The Idempotency-Key was already used with a different request body.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorEnvelope'
              example:
                error:
                  code: idempotency_key_reuse
                  message: >-
                    This Idempotency-Key was already used with a different
                    request body.
        '429':
          $ref: '#/components/responses/RateLimited'
        '500':
          $ref: '#/components/responses/InternalError'
        '502':
          $ref: '#/components/responses/UpstreamError'
        '503':
          $ref: '#/components/responses/UpstreamUnavailable'
components:
  headers:
    X-RateLimit-Limit:
      description: The limit of the rate window closest to exhaustion.
      schema:
        type: integer
    X-RateLimit-Remaining:
      description: Requests remaining in that window.
      schema:
        type: integer
    X-RateLimit-Reset:
      description: Unix timestamp (seconds) when that window resets.
      schema:
        type: integer
  schemas:
    ErrorEnvelope:
      type: object
      required:
        - error
      properties:
        error:
          type: object
          required:
            - code
            - message
          properties:
            code:
              type: string
              description: Stable machine-readable error code.
            message:
              type: string
            retry_after:
              type: integer
              description: Seconds to wait before retrying (rate-limit errors only).
    LegacyErrorEnvelope:
      type: object
      required:
        - error
      description: |
        Legacy shape used ONLY by the shared subscription middleware: a plain
        string `error` field. Seen on `403` when the subscription has lapsed
        (string starts with "subscription_required:") and on `500` when
        subscription verification fails (string starts with "internal_error:").
      properties:
        error:
          type: string
          example: >-
            subscription_required: The SuperX API requires an active
            subscription
  responses:
    Unauthorized:
      description: >-
        Missing/malformed Authorization header (`unauthorized`) or an
        unknown/revoked key (`invalid_api_key`).
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorEnvelope'
          example:
            error:
              code: invalid_api_key
              message: Unknown or revoked API key
    AccountNotFound:
      description: account_id is not one of your accounts.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorEnvelope'
          example:
            error:
              code: account_not_found
              message: No account with that id belongs to this key
    RateLimited:
      description: Rate limit exceeded (limits vary by plan). Honor Retry-After.
      headers:
        Retry-After:
          description: Seconds to wait before retrying.
          schema:
            type: integer
        X-RateLimit-Limit:
          $ref: '#/components/headers/X-RateLimit-Limit'
        X-RateLimit-Remaining:
          $ref: '#/components/headers/X-RateLimit-Remaining'
        X-RateLimit-Reset:
          $ref: '#/components/headers/X-RateLimit-Reset'
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorEnvelope'
          example:
            error:
              code: rate_limited
              message: >-
                Rate limit exceeded for the Pro plan (30 requests/min). Upgrade
                for higher limits.
              retry_after: 42
    InternalError:
      description: >-
        Unexpected server error. May also use the legacy string envelope when
        subscription verification fails.
      content:
        application/json:
          schema:
            oneOf:
              - $ref: '#/components/schemas/ErrorEnvelope'
              - $ref: '#/components/schemas/LegacyErrorEnvelope'
          example:
            error:
              code: internal_error
              message: Failed to fetch posts
    UpstreamError:
      description: A dependent SuperX service returned an unexpected response.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorEnvelope'
          example:
            error:
              code: upstream_error
              message: Failed to fetch scheduled posts. Try again shortly.
    UpstreamUnavailable:
      description: >-
        The scheduling service is temporarily unreachable. Safe to retry; reuse
        your Idempotency-Key on POST.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorEnvelope'
          example:
            error:
              code: upstream_unavailable
              message: >-
                The scheduling service is temporarily unavailable. Retry with
                the same Idempotency-Key.
  securitySchemes:
    apiKey:
      type: http
      scheme: bearer
      description: >-
        A SuperX API key ("sxk_..."), created in the SuperX app under Account >
        API / MCP / CLI. Keys are server-side secrets.

````