> ## 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, or publish now

> Creates a post: a draft when `scheduled_for` is omitted, a scheduled
post otherwise. Works for your main account or any account linked to it
(`account_id`); accounts shared with you are read-only. Supports the
`Idempotency-Key` header for safe retries (see the Idempotency guide).
Successful creation returns `201`.

**Publishing now.** Send `scheduled_for: "now"` and the post goes to X
immediately. This is irreversible, so the rules are tighter:

- `Idempotency-Key` is REQUIRED (`400 invalid_parameter` without it).
  Reuse the same key on any retry: it never publishes twice.
- `title` and `scratchpad` are rejected with `400` (a published post
  has no draft to organize), and Bluesky is never cross-posted.
- A retry that arrives while the first attempt is still publishing
  returns `409 idempotency_in_flight` with a `Retry-After` header.
  After that window the API checks whether the first attempt landed
  and replays its result instead of posting again.
- The `201` carries `status: "sent"` with `posted_at`, `x_post_id`
  and `url`, and `scheduled_for: null`.
- Advanced settings and Auto DM inherit your Default Post Settings
  exactly as they do for a scheduled post.
- A thread that fails part way through leaves no scheduled-post record
  at all, so check `GET /v1/posts` before retrying: the parts X did
  accept are already live.

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`,
`auto_dm`, `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` direct-messages the people who reply to or repost the post
once it is live. Your plan caps how many posts a month may carry one
(`posts_with_auto_dm` in `GET /v1/dm/limits`): when that cap stops
it, the post is still created and the response carries
`auto_dm_skipped: true` instead of failing. Reading a post back shows
that an auto DM is attached but never its message text.




## 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: Datasets
    description: |
      The audience collections Ask SuperX builds in the app: the repliers,
      quoters or reposters of a post, the members of an X list, your own
      posts or replies, or a research brief.

      Collect a new one with `POST /v1/datasets` (a big collection answers
      202 and finishes in the background), read it, export it, or copy the
      people in it into a contact list you created. Datasets are kept for 30
      days, and the ones Ask SuperX builds in the app show up here too.
  - name: Engage
    description: |
      The account's saved Engage feeds and the candidate posts in them, for
      an agent to score and a person to act on.

      Read-only by design. These endpoints return feed candidates for a
      person to review; replies are written and sent by a person in the
      SuperX app, which is why there is no reply endpoint here. Sending
      spammy, automated, or AI-generated replies that read as inauthentic
      may get your X account suspended under X's inauthentic-behavior
      rules and your SuperX account terminated. AI suggestions must be
      reviewed and meaningfully edited before they are sent, and you are
      solely responsible for what you post. Reply activity is logged and
      may be audited.
  - name: X Lookups
    description: |
      Read any public post, its top replies, any public profile, or an
      account's latest posts LIVE from X, rather than from SuperX's stored
      data.

      These are owner-scoped, so none of them take an `account_id`: nothing
      about a public lookup is per-X-account. They cost the tighter
      live-enrichment allowance and share a daily allowance of 300 live
      lookups with Ask SuperX inside the app, so use them for what you
      actually need rather than to sweep. Repeat lookups within 15 minutes
      may be served from a short-lived server-side cache.
  - name: Tools
    description: |
      The composer helpers from the SuperX app, over the API: rewrite a post,
      edit one selected piece of it, apply one preset rewrite, check a claim,
      or compare two versions.

      Every one of them returns TEXT and writes nothing. Nothing here is
      posted, scheduled or sent; save what you keep with
      `POST /v1/posts/draft` or `POST /v1/scheduled-posts`. They cost AI
      credits, measured from the models' real cost, and spend no live-data
      allowance.
  - name: Media
  - name: Workers
    description: |
      The posts the account's Workers have written, and the three things a
      person does with one: save it as a draft, schedule it, or dismiss it.

      A Worker is a scheduled AI writer set up in the SuperX app. Creating,
      editing and running one stays in the app, so there is no create or run
      endpoint here. What a run produces lands in the app's "To review" queue
      and is read with `GET /v1/workers/suggestions`.

      NOTHING HERE POSTS TO X. Drafting or scheduling a suggestion writes a
      post the user can see in the app and on `GET /v1/scheduled-posts`,
      exactly like the app's own buttons. AI output must be reviewed and
      meaningfully edited by a person before it goes out, so show the text to
      the user and confirm the time before you schedule anything.
  - name: Scheduling
  - name: Tags
  - name: Context
  - name: Queue
  - name: DMs
    description: |
      Queue direct messages into the account's own DM pipeline, and read or
      cancel what is waiting.

      NOTHING HERE SENDS A MESSAGE. `POST /v1/dm/campaigns` enqueues; the
      SuperX app's scheduler is what sends, within the account's daily and
      monthly DM limits, so the create response is counts, not deliveries.
      Unsent messages can be cancelled until the scheduler picks them up.

      You are responsible for the messages you queue. Unsolicited or
      automated bulk DMs may get an X account suspended under X's rules and
      a SuperX account terminated, so confirm the recipient list and the
      exact wording with the person on whose behalf you are queueing.
  - name: Articles
  - name: Meta
paths:
  /v1/scheduled-posts:
    post:
      tags:
        - Scheduling
      summary: Create a draft or scheduled post, or publish now
      description: |
        Creates a post: a draft when `scheduled_for` is omitted, a scheduled
        post otherwise. Works for your main account or any account linked to it
        (`account_id`); accounts shared with you are read-only. Supports the
        `Idempotency-Key` header for safe retries (see the Idempotency guide).
        Successful creation returns `201`.

        **Publishing now.** Send `scheduled_for: "now"` and the post goes to X
        immediately. This is irreversible, so the rules are tighter:

        - `Idempotency-Key` is REQUIRED (`400 invalid_parameter` without it).
          Reuse the same key on any retry: it never publishes twice.
        - `title` and `scratchpad` are rejected with `400` (a published post
          has no draft to organize), and Bluesky is never cross-posted.
        - A retry that arrives while the first attempt is still publishing
          returns `409 idempotency_in_flight` with a `Retry-After` header.
          After that window the API checks whether the first attempt landed
          and replays its result instead of posting again.
        - The `201` carries `status: "sent"` with `posted_at`, `x_post_id`
          and `url`, and `scheduled_for: null`.
        - Advanced settings and Auto DM inherit your Default Post Settings
          exactly as they do for a scheduled post.
        - A thread that fails part way through leaves no scheduled-post record
          at all, so check `GET /v1/posts` before retrying: the parts X did
          accept are already live.

        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`,
        `auto_dm`, `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` direct-messages the people who reply to or repost the post
        once it is live. Your plan caps how many posts a month may carry one
        (`posts_with_auto_dm` in `GET /v1/dm/limits`): when that cap stops
        it, the post is still created and the response carries
        `auto_dm_skipped: true` instead of failing. Reading a post back shows
        that an auto DM is attached but never its message text.
      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:
                  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. The literal string `"now"` publishes to X immediately
                    and requires an `Idempotency-Key` (see the operation
                    description).
                  oneOf:
                    - type: string
                      format: date-time
                    - type: string
                      enum:
                        - now
                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.
                auto_dm:
                  allOf:
                    - $ref: '#/components/schemas/AutoDm'
                  description: >-
                    Auto DM: message the people who reply to or repost this post
                    once it is live. Omit to inherit your defaults; `null` turns
                    it off for this post.
                super_followers_only:
                  type: boolean
                  description: Post to Super Followers only. Omit to inherit your defaults.
                account_id:
                  type: string
                  description: >-
                    Any account you own, meaning your main account (the default
                    when omitted) or one linked to it. An account shared with
                    you returns `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
              publish_now:
                summary: Publish immediately (Idempotency-Key required)
                value:
                  text: Shipping now.
                  scheduled_for: now
      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, adding `?status=sent` for a post
            published with `scheduled_for: "now"`.
          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
                          - sent
                        description: '`sent` only for `scheduled_for: "now"`.'
                      scheduled_for:
                        type: string
                        format: date-time
                        nullable: true
                        description: >-
                          Null for a draft and for a post published with
                          `scheduled_for: "now"`.
                      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
                      posted_at:
                        type: string
                        format: date-time
                        nullable: true
                        description: >-
                          When the post went out. Present only for
                          `scheduled_for: "now"`.
                      x_post_id:
                        type: string
                        nullable: true
                        description: >-
                          The X post id. Present only for `scheduled_for:
                          "now"`.
                      url:
                        type: string
                        nullable: true
                        description: >-
                          Permalink to the post on X. Present only for
                          `scheduled_for: "now"`.
                      auto_dm_skipped:
                        type: boolean
                        description: >-
                          Present (and true) only when a plan limit stripped the
                          inherited Auto DM from this post. Absent otherwise,
                          and always absent from a result the API recovered
                          after an interrupted publish (the flag is not stored
                          on the post), so treat its absence as "unknown" on a
                          retried request.
              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`), an account shared with you
            (`writes_main_account_only`; shared accounts are read-only through
            the API, your own linked accounts are not), onboarding not finished
            (`onboarding_required`), post quota used up
            (`post_quota_exceeded`), the connected X account needing to be
            re-authorized in the SuperX app (`reauth_required`, publishing
            only), 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: >-
                    Accounts shared with you are read-only through the API.
                    Writes work on your own main and linked accounts.
        '404':
          $ref: '#/components/responses/AccountNotFound'
        '409':
          description: >-
            The Idempotency-Key was already used with a different request body
            (`idempotency_key_reuse`); or, when publishing now, an earlier
            request with the same key is still publishing
            (`idempotency_in_flight`, with a `Retry-After` header: wait, then
            retry the SAME key) or the post has already been published
            (`post_already_published`).
          headers:
            Retry-After:
              description: Seconds to wait before retrying, on `idempotency_in_flight`.
              schema:
                type: integer
          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:
  schemas:
    AutoDm:
      type: object
      nullable: true
      required:
        - message
      description: |
        Auto DM settings for one post. The DM goes to the people who reply to
        or repost the post once it is live, sent by the SuperX app's
        scheduler inside the account's DM limits.
      properties:
        message:
          type: string
          minLength: 1
          maxLength: 1000
          description: >-
            The direct message. `[name]`, `[first]` and `[handle]` are filled in
            per recipient. Always required on a non-null `auto_dm`.
        triggers:
          type: object
          additionalProperties: false
          description: >-
            Who gets the DM. At least one must be true; defaults to reply only.
            Any other key is rejected with `400 invalid_parameter`.
          properties:
            reply:
              type: boolean
              description: DM the people who reply to the post.
            repost:
              type: boolean
              description: DM the people who repost the post.
            retweet:
              type: boolean
              description: >-
                Alias of `repost`, accepted so the value a post reads back
                (which reports `retweet`) can be sent straight back. Sending
                both with different values is a `400`.
        enabled:
          type: boolean
          default: true
          description: >-
            `false` behaves exactly like sending `auto_dm: null`: the Auto DM is
            cleared and nothing is stored. Prefer `null`.
        max_dms:
          type: integer
          minimum: 1
          maximum: 100
          default: 100
          description: >-
            Most people to DM for this post. The plan's per-post cap still
            applies.
        batch_mode:
          type: boolean
          description: Send the DMs in one batch rather than as engagement arrives.
    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
  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
  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.

````