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

# Get posts from an Engage feed

> Candidate posts from one saved feed, with the author profile and
engagement metrics you need to score them for relevance, author size
and recency.

Paging works through `exclude_post_ids`, not page numbers: pass the
ids you already hold to get the next batch. There is no `pagination`
object; `has_more` tells you whether the feed had more to give.

`limit` applies to keyword feeds. List feeds ignore it upstream and
return one page per fetch: about 10 posts for a member list, 20 to 25
for an imported X list (`limit` only trims that page). The size
follows the list's resolved kind rather than the feed's `type`, so a
`list` feed backed by a pure imported X list pages like an `x_list`
feed. Page list feeds with `exclude_post_ids` instead of raising
`limit`.

Each fetch charges the plan's feed bucket, and a list feed that
rotates its members costs 3 units instead of 1. On a keyword feed a
50-post page costs exactly the same as a 20-post page, so ask for
`limit=50` a few times a day and filter on your side rather than
polling; feeds refresh over hours, so fetching more often than
hourly returns the same posts. Feed fetches also run a few at a time
across all API users; on a `429` with `Retry-After`, wait and retry.
The bucket is charged before the fetch, so a fetch that then fails
upstream still costs its units.

Posts returned here count as seen and are demoted in later fetches.
On a list feed, paging with `exclude_post_ids` also advances, and
`fresh=true` resets, the same list cursor the SuperX app uses, so
both move the position a person browsing that feed in the app sees.
A plain fetch after a pause resets that cursor too, matching the
app's own session timeout.

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.




## OpenAPI

````yaml /api-reference/openapi.yaml get /v1/engage/feeds/{id}/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/engage/feeds/{id}/posts:
    get:
      tags:
        - Engage
      summary: Get posts from an Engage feed
      description: |
        Candidate posts from one saved feed, with the author profile and
        engagement metrics you need to score them for relevance, author size
        and recency.

        Paging works through `exclude_post_ids`, not page numbers: pass the
        ids you already hold to get the next batch. There is no `pagination`
        object; `has_more` tells you whether the feed had more to give.

        `limit` applies to keyword feeds. List feeds ignore it upstream and
        return one page per fetch: about 10 posts for a member list, 20 to 25
        for an imported X list (`limit` only trims that page). The size
        follows the list's resolved kind rather than the feed's `type`, so a
        `list` feed backed by a pure imported X list pages like an `x_list`
        feed. Page list feeds with `exclude_post_ids` instead of raising
        `limit`.

        Each fetch charges the plan's feed bucket, and a list feed that
        rotates its members costs 3 units instead of 1. On a keyword feed a
        50-post page costs exactly the same as a 20-post page, so ask for
        `limit=50` a few times a day and filter on your side rather than
        polling; feeds refresh over hours, so fetching more often than
        hourly returns the same posts. Feed fetches also run a few at a time
        across all API users; on a `429` with `Retry-After`, wait and retry.
        The bucket is charged before the fetch, so a fetch that then fails
        upstream still costs its units.

        Posts returned here count as seen and are demoted in later fetches.
        On a list feed, paging with `exclude_post_ids` also advances, and
        `fresh=true` resets, the same list cursor the SuperX app uses, so
        both move the position a person browsing that feed in the app sees.
        A plain fetch after a pause resets that cursor too, matching the
        app's own session timeout.

        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.
      operationId: getEngageFeedPosts
      parameters:
        - name: id
          in: path
          required: true
          description: Feed id from `GET /v1/engage/feeds`.
          schema:
            type: string
        - $ref: '#/components/parameters/AccountId'
        - name: limit
          in: query
          description: >-
            Posts to return, up to 50. Default 20. Applies to keyword feeds;
            list feeds return one page per fetch whatever you ask for, about 10
            posts for a member list and 20 to 25 for an imported X list. On a
            keyword feed a big page costs the same as a small one.
          schema:
            type: integer
            minimum: 1
            maximum: 50
            default: 20
        - name: mode
          in: query
          description: >-
            Ranking for keyword feeds. `top` (default) blends quality and
            relevance, `latest` is pure recency.
          schema:
            type: string
            enum:
              - top
              - latest
            default: top
        - name: fresh
          in: query
          description: Skip the short-lived result cache and refetch. Default false.
          schema:
            type: boolean
            default: false
        - name: include_replied
          in: query
          description: >-
            Keep posts the account already replied to, flagged with `replied:
            true`. Default false removes them.
          schema:
            type: boolean
            default: false
        - name: exclude_post_ids
          in: query
          description: >-
            Comma-separated post ids to leave out, up to 100. This is how you
            page.
          schema:
            type: string
      responses:
        '200':
          description: Candidate posts from the 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:
                    type: array
                    items:
                      $ref: '#/components/schemas/EngageFeedPost'
                  has_more:
                    type: boolean
                  feed:
                    type: object
                    properties:
                      id:
                        type: string
                      name:
                        type: string
                      type:
                        type: string
                        enum:
                          - keywords
                          - list
                          - x_list
              example:
                data:
                  - id: '1941300000000000002'
                    text: We doubled activation by rewriting onboarding emails.
                    created_at: '2026-09-01T09:41:00.000Z'
                    url: https://x.com/founderhandle/status/1941300000000000002
                    author:
                      id: '944883311'
                      username: founderhandle
                      name: Founder Name
                      description: Bootstrapping a SaaS in public.
                      followers_count: 4210
                      following_count: 388
                      verified: true
                    metrics:
                      likes: 142
                      replies: 18
                      reposts: 9
                      bookmarks: 27
                      impressions: 21400
                    media: []
                has_more: true
                feed:
                  id: feed_kw_1
                  name: Bootstrapped SaaS
                  type: keywords
        '400':
          $ref: '#/components/responses/InvalidParameter'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/SubscriptionRequired'
        '404':
          $ref: '#/components/responses/FeedNotFound'
        '429':
          $ref: '#/components/responses/FeedRateLimited'
        '500':
          $ref: '#/components/responses/InternalError'
        '502':
          $ref: '#/components/responses/UpstreamError'
        '503':
          $ref: '#/components/responses/UpstreamUnavailable'
components:
  parameters:
    AccountId:
      name: account_id
      in: query
      required: false
      description: >-
        Account to act on, from `GET /v1/accounts`. Defaults to your main
        account. An id outside your accounts returns `404 account_not_found`.
      schema:
        type: string
  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:
    EngageFeedPost:
      type: object
      properties:
        id:
          type: string
        text:
          type: string
          description: Post text with shortened links expanded.
        created_at:
          type: string
          format: date-time
          nullable: true
        url:
          type: string
        author:
          $ref: '#/components/schemas/EngageFeedPostAuthor'
        metrics:
          type: object
          properties:
            likes:
              type: integer
            replies:
              type: integer
            reposts:
              type: integer
            bookmarks:
              type: integer
            impressions:
              type: integer
        media:
          type: array
          description: Image URLs attached to the post, best effort.
          items:
            type: string
        quoted_post:
          type: object
          description: Present only when the post quotes another one.
          properties:
            id:
              type: string
            text:
              type: string
            author_username:
              type: string
              nullable: true
        replied:
          type: boolean
          description: >-
            Present only when include_replied=true. True when the account
            already replied to this post.
    EngageFeedPostAuthor:
      type: object
      nullable: true
      properties:
        id:
          type: string
          nullable: true
        username:
          type: string
          nullable: true
        name:
          type: string
          nullable: true
        description:
          type: string
          nullable: true
          description: The author's X bio. Not always present on list feeds.
        followers_count:
          type: integer
          nullable: true
        following_count:
          type: integer
          nullable: true
        verified:
          type: boolean
    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
    SubscriptionRequired:
      description: |
        Subscription lapsed. NOTE the legacy body shape: `error` is a plain
        string here, not the `{ code, message }` object. Read-only keys on
        write endpoints instead get the object envelope with code
        `insufficient_scope`.
      content:
        application/json:
          schema:
            oneOf:
              - $ref: '#/components/schemas/LegacyErrorEnvelope'
              - $ref: '#/components/schemas/ErrorEnvelope'
          example:
            error: >-
              subscription_required: The SuperX API requires an active
              subscription
    FeedNotFound:
      description: >-
        The feed id is not one of your Engage feeds (`feed_not_found`), the feed
        points at a contact list that no longer exists (`list_not_found`), or
        account_id is not one of your accounts (`account_not_found`).
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorEnvelope'
          example:
            error:
              code: feed_not_found
              message: No Engage feed with that id belongs to this account.
    FeedRateLimited:
      description: >-
        The plan's feed-fetch allowance is spent, or feed fetches are busy
        across all API users right now. Honor Retry-After. No feed units are
        charged when the request is rejected; the request still consumed one
        unit of the ordinary read budget, and the X-RateLimit-* headers on this
        response describe that read bucket, not the feed bucket.
      headers:
        Retry-After:
          description: Seconds to wait before retrying.
          schema:
            type: integer
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorEnvelope'
          example:
            error:
              code: rate_limited
              message: >-
                Rate limit exceeded for the Pro plan (5 feed fetches/min).
                Upgrade for higher limits. A list feed that rotates its members
                costs 3 fetches. Retry after 27 seconds.
              retry_after: 27
              remaining_day: 41
    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.

````