> ## 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 an Engage feed

> Save a new Engage feed on the account: a set of keywords, a public X
list, or one of the account's own contact lists. The feed appears in
`GET /v1/engage/feeds`, can be fetched with
`GET /v1/engage/feeds/{id}/posts`, and shows up for the person in the
SuperX app's Engage tab.

The new feed does NOT become the feed the app has open: the API must
not move someone's view while they are working in it. The response
carries the account's current `active` feed unchanged.

Send exactly ONE source: `keywords` (1-5), `x_list_id` or
`x_list_url`, or `list_id`. `type` must agree with the fields you
send. An X list is looked up live and only PUBLIC lists are accepted,
so those calls also consume one unit of the tighter enrichment
allowance; keyword and contact-list feeds consume none. Up to 8 feeds
per account. Works for your main account or any account linked to it
(`account_id`); accounts shared with you are read-only.




## OpenAPI

````yaml /api-reference/openapi.yaml post /v1/engage/feeds
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/engage/feeds:
    post:
      tags:
        - Engage
      summary: Create an Engage feed
      description: |
        Save a new Engage feed on the account: a set of keywords, a public X
        list, or one of the account's own contact lists. The feed appears in
        `GET /v1/engage/feeds`, can be fetched with
        `GET /v1/engage/feeds/{id}/posts`, and shows up for the person in the
        SuperX app's Engage tab.

        The new feed does NOT become the feed the app has open: the API must
        not move someone's view while they are working in it. The response
        carries the account's current `active` feed unchanged.

        Send exactly ONE source: `keywords` (1-5), `x_list_id` or
        `x_list_url`, or `list_id`. `type` must agree with the fields you
        send. An X list is looked up live and only PUBLIC lists are accepted,
        so those calls also consume one unit of the tighter enrichment
        allowance; keyword and contact-list feeds consume none. Up to 8 feeds
        per account. Works for your main account or any account linked to it
        (`account_id`); accounts shared with you are read-only.
      operationId: createEngageFeed
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - name
                - type
              properties:
                name:
                  type: string
                  minLength: 1
                  maxLength: 40
                  description: Feed name shown in SuperX.
                type:
                  type: string
                  enum:
                    - keywords
                    - x_list
                    - list
                  description: Must match the source fields sent below.
                keywords:
                  type: array
                  minItems: 1
                  maxItems: 5
                  items:
                    type: string
                    maxLength: 100
                  description: >-
                    For type keywords. Trimmed, de-duplicated
                    case-insensitively.
                x_list_id:
                  type: string
                  description: >-
                    For type x_list. A numeric X list id. Use this OR
                    x_list_url.
                x_list_url:
                  type: string
                  description: >-
                    For type x_list. A link like
                    https://x.com/i/lists/1234567890.
                list_id:
                  type: string
                  description: >-
                    For type list. A contact list id from `GET
                    /v1/contact-lists`.
                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`.
            example:
              name: Bootstrapped SaaS
              type: keywords
              keywords:
                - bootstrapped saas
                - indie hackers
      responses:
        '201':
          description: >-
            The created feed. `active` is false unless the account had no active
            feed.
          headers:
            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:
                    $ref: '#/components/schemas/EngageFeed'
              example:
                data:
                  id: V1StGXR8_Z5jdHi6B-myT
                  name: Bootstrapped SaaS
                  type: keywords
                  keywords:
                    - bootstrapped saas
                    - indie hackers
                  active: false
                  fetch_units: 1
        '400':
          $ref: '#/components/responses/InvalidParameter'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/WriteForbidden'
        '404':
          $ref: '#/components/responses/FeedSourceNotFound'
        '409':
          $ref: '#/components/responses/FeedLimitReached'
        '429':
          $ref: '#/components/responses/RateLimited'
        '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:
    EngageFeed:
      type: object
      properties:
        id:
          type: string
          description: Pass this to GET /v1/engage/feeds/{id}/posts.
        name:
          type: string
        type:
          type: string
          enum:
            - keywords
            - list
            - x_list
          description: >-
            keywords = a saved keyword search, list = a SuperX contact list,
            x_list = an X list.
        keywords:
          type: array
          description: Keyword feeds only.
          items:
            type: string
        list_id:
          type: string
          description: Contact list id, list feeds only.
        x_list_id:
          type: string
          description: X list id, x_list feeds only.
        list_name:
          type: string
          description: List feeds only.
        active:
          type: boolean
          description: Whether this is the feed currently selected in the app.
        fetch_units:
          type: integer
          description: >-
            Feed-bucket units one fetch of this feed costs. List feeds count as
            up to 3 (a pure imported X list resolves to 1 at fetch time);
            everything else is 1.
    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:
    InvalidParameter:
      description: A parameter is missing, malformed, or out of range.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorEnvelope'
          example:
            error:
              code: invalid_parameter
              message: since must be a UTC ISO-8601 timestamp
    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
    WriteForbidden:
      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), or a lapsed subscription (legacy
        string envelope).
      content:
        application/json:
          schema:
            oneOf:
              - $ref: '#/components/schemas/ErrorEnvelope'
              - $ref: '#/components/schemas/LegacyErrorEnvelope'
          example:
            error:
              code: insufficient_scope
              message: >-
                This API key is read-only. Create a key with the write scope to
                use this endpoint.
    FeedSourceNotFound:
      description: >-
        The feed's source could not be resolved: the X list is private, deleted,
        or never existed (`x_list_not_found`), the `list_id` is not one of your
        contact lists (`list_not_found`), the feed id is not one of your feeds
        (`feed_not_found`, on update), or account_id is not one of your accounts
        (`account_not_found`).
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorEnvelope'
          example:
            error:
              code: x_list_not_found
              message: >-
                That X list is private or unavailable. Only public lists can be
                used as a feed.
    FeedLimitReached:
      description: The account already holds the maximum number of saved Engage feeds (8).
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorEnvelope'
          example:
            error:
              code: feed_limit_reached
              message: >-
                This account already has the maximum number of saved Engage
                feeds. Delete one before adding another.
    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
    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.

````