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

# Get list tweets

> Retrieve tweets from an X list with cursor-based pagination

<blockquote className="agent-llms-directive">
  For the complete documentation index, see <a href="/llms.txt">llms.txt</a>.
</blockquote>

<Note>
  Requested result counts are upper bounds for paid authenticated calls. When remaining credits cannot cover the full page or ID list, Xquik returns fewer results. If zero paid results are affordable, it returns `402 insufficient_credits`.
</Note>

<Callout icon="coins" color="#5c3327">
  **1 credit per tweet returned** · [All plans](https://xquik.com/#pricing) from \$0.00012/credit
</Callout>

<CodeGroup>
  ```bash cURL theme={null}
  curl "https://xquik.com/api/v1/x/lists/1234567890/tweets" \
    -H "x-api-key: xq_YOUR_KEY_HERE" | jq
  ```

  ```javascript Node.js theme={null}
  const listId = "1234567890";
  const response = await fetch(`https://xquik.com/api/v1/x/lists/${listId}/tweets`, {
    headers: { "x-api-key": "xq_YOUR_KEY_HERE" },
  });
  const data = await response.json();
  const tweetRows = data.tweets.map((tweet) => ({
    list_id: listId,
    tweet_id: tweet.id,
    text: tweet.text,
    author_id: tweet.author?.id ?? null,
    author_username: tweet.author?.username ?? null,
    author_name: tweet.author?.name ?? null,
    author_followers: tweet.author?.followers ?? null,
    author_verified: tweet.author?.verified ?? null,
    author_profile_picture: tweet.author?.profilePicture ?? null,
    created_at: tweet.createdAt ?? null,
    like_count: tweet.likeCount ?? null,
    reply_count: tweet.replyCount ?? null,
    retweet_count: tweet.retweetCount ?? null,
    media_urls: tweet.media?.map((item) => item.mediaUrl).filter(Boolean) ?? [],
  }));
  const nextCursor = data.has_next_page ? data.next_cursor : null;

  for (const row of tweetRows) {
    process.stdout.write(`${JSON.stringify(row)}\n`);
  }
  if (nextCursor !== null) {
    process.stdout.write(`${JSON.stringify({ list_id: listId, next_cursor: nextCursor })}\n`);
  }
  ```

  ```python Python theme={null}
  import json
  import requests

  list_id = "1234567890"
  response = requests.get(
      f"https://xquik.com/api/v1/x/lists/{list_id}/tweets",
      headers={"x-api-key": "xq_YOUR_KEY_HERE"},
  )
  data = response.json()
  tweet_rows = [
      {
          "list_id": list_id,
          "tweet_id": tweet["id"],
          "text": tweet.get("text"),
          "author_id": (tweet.get("author") or {}).get("id"),
          "author_username": (tweet.get("author") or {}).get("username"),
          "author_name": (tweet.get("author") or {}).get("name"),
          "author_followers": (tweet.get("author") or {}).get("followers"),
          "author_verified": (tweet.get("author") or {}).get("verified"),
          "author_profile_picture": (tweet.get("author") or {}).get("profilePicture"),
          "created_at": tweet.get("createdAt"),
          "like_count": tweet.get("likeCount"),
          "reply_count": tweet.get("replyCount"),
          "retweet_count": tweet.get("retweetCount"),
          "media_urls": [
              item["mediaUrl"]
              for item in tweet.get("media", [])
              if item.get("mediaUrl")
          ],
      }
      for tweet in data["tweets"]
  ]
  next_cursor = data["next_cursor"] if data["has_next_page"] else None

  for row in tweet_rows:
      print(json.dumps(row))
  if next_cursor is not None:
      print(json.dumps({"list_id": list_id, "next_cursor": next_cursor}))
  ```
</CodeGroup>

The Node.js & Python snippets shape one durable row per returned list tweet
instead of printing the full response page. Persist the final `next_cursor`
row when `has_next_page` is true, then pass it back as `cursor` for the next
page.

## Direct list tweet handoff

Use `GET /x/lists/{id}/tweets` when a CRM, warehouse, newsroom, monitoring
job, or agent needs tweets from a curated X List.

Store `list_id`, `tweet_id`, `text`, `author_id`, `author_username`,
`author_name`, `author_followers`, `author_verified`,
`author_profile_picture`, `created_at`, engagement counts, & `media_urls` for
each row. Keep `has_next_page` & `next_cursor` with the export checkpoint so
the next run can resume the list timeline without duplicating earlier rows.

Use `sinceTime` & `untilTime` for bounded backfills, and set
`includeReplies=true` only when reply tweets belong in the downstream queue.

<CardGroup cols={2}>
  <Card title="List tweet rows" icon="message-square-text">
    Store `tweets[]` as timeline rows from accounts in the list. Use the row
    shape above for newsroom, monitoring, CRM, and warehouse imports.
  </Card>

  <Card title="Next page" icon="arrow-right">
    Store `has_next_page` and `next_cursor`. Only request another page when
    `has_next_page` is true.
  </Card>

  <Card title="Default page" icon="rows-3">
    Direct calls use the default paid tweet page size. Treat the returned
    `tweets.length` as the row count returned for this page.
  </Card>

  <Card title="Time window" icon="calendar-range">
    Use `sinceTime` and `untilTime` for bounded backfills or repeat sync jobs.
  </Card>

  <Card title="Reply filter" icon="message-square-reply">
    Leave `includeReplies` unset for a cleaner list timeline. Set
    `includeReplies=true` only when reply tweets belong downstream.
  </Card>

  <Card title="Saved export" icon="file-spreadsheet">
    Use `list_post_extractor` when the workflow needs a saved job with
    CSV/JSON/XLSX output.
  </Card>
</CardGroup>

## Path parameters

<ParamField path="id" type="string" required>
  List ID (numeric string).
</ParamField>

## Query parameters

<ParamField query="cursor" type="string">
  Pagination cursor from a previous response. Omit for the first page.
</ParamField>

<ParamField query="sinceTime" type="string">
  Unix timestamp in seconds. Only return tweets after this time.
</ParamField>

<ParamField query="untilTime" type="string">
  Unix timestamp in seconds. Only return tweets before this time.
</ParamField>

<ParamField query="includeReplies" type="boolean">
  Include reply tweets. Default: `false`.
</ParamField>

## Which list endpoint?

<CardGroup cols={2}>
  <Card title="List tweets" icon="message-square-text">
    Use `GET /x/lists/{id}/tweets` for tweets from accounts in the list.
  </Card>

  <Card title="List members" icon="users">
    Use [`GET /x/lists/{id}/members`](/api-reference/x/list-members) for
    accounts the list owner added to the list.
  </Card>

  <Card title="List followers" icon="user-plus">
    Use [`GET /x/lists/{id}/followers`](/api-reference/x/list-followers) for
    accounts that follow the list.
  </Card>

  <Card title="Bulk list jobs" icon="file-spreadsheet">
    Use [`Create extraction`](/api-reference/extractions/create) with
    `list_post_extractor`, `list_member_extractor`, or `list_follower_explorer`
    when the workflow needs a saved export.
  </Card>
</CardGroup>

## Headers

<ParamField header="x-api-key" type="string" required>
  Your API key. Session cookie authentication is also supported.
</ParamField>

## Response

<Tabs>
  <Tab title="200 OK">
    <ResponseField name="tweets" type="object[]">
      Array of tweets from the list.

      <Expandable title="Tweet object fields">
        <ResponseField name="id" type="string">Tweet ID.</ResponseField>
        <ResponseField name="text" type="string">Tweet text.</ResponseField>
        <ResponseField name="type" type="string">Tweet type. Omitted if unavailable.</ResponseField>
        <ResponseField name="createdAt" type="string">ISO 8601 creation timestamp.</ResponseField>
        <ResponseField name="isNoteTweet" type="boolean">Whether this is a Note Tweet. Omitted if unavailable.</ResponseField>
        <ResponseField name="likeCount" type="number">Like count. Omitted if unavailable.</ResponseField>
        <ResponseField name="retweetCount" type="number">Retweet count. Omitted if unavailable.</ResponseField>
        <ResponseField name="replyCount" type="number">Reply count. Omitted if unavailable.</ResponseField>
        <ResponseField name="quoteCount" type="number">Quote tweet count. Omitted if unavailable.</ResponseField>
        <ResponseField name="viewCount" type="number">View count. Omitted if unavailable.</ResponseField>
        <ResponseField name="bookmarkCount" type="number">Bookmark count. Omitted if unavailable.</ResponseField>
        <ResponseField name="url" type="string">Permalink URL on X. Omitted if unavailable.</ResponseField>
        <ResponseField name="lang" type="string">Tweet language code. Omitted if unavailable.</ResponseField>
        <ResponseField name="isReply" type="boolean">Whether the tweet is a reply. Omitted if unavailable.</ResponseField>
        <ResponseField name="inReplyToId" type="string">Tweet ID being replied to. Omitted if not a reply.</ResponseField>
        <ResponseField name="inReplyToUserId" type="string">User ID being replied to. Omitted if unavailable.</ResponseField>
        <ResponseField name="inReplyToUsername" type="string">Username being replied to. Omitted if unavailable.</ResponseField>
        <ResponseField name="conversationId" type="string">Conversation thread ID. Omitted if unavailable.</ResponseField>
        <ResponseField name="source" type="string">Client used to post the tweet. Omitted if unavailable.</ResponseField>
        <ResponseField name="displayTextRange" type="number[]">Start and end offsets for rendered tweet text. Omitted if unavailable.</ResponseField>
        <ResponseField name="isLimitedReply" type="boolean">Whether replies are limited. Omitted if unavailable.</ResponseField>
        <ResponseField name="isQuoteStatus" type="boolean">Whether this tweet quotes another tweet. Omitted if unavailable.</ResponseField>
        <ResponseField name="entities" type="object">Parsed entities. Omitted if unavailable.</ResponseField>
        <ResponseField name="contentDisclosure" type="object">Disclosure metadata for paid partnership and AI-generated media labels. Includes `advertising.isPaidPromotion` and `aiGenerated.hasAiGeneratedMedia` when X returns them. Omitted if unavailable.</ResponseField>

        <ResponseField name="author" type="object">
          Tweet author profile. Omitted if unavailable.

          <Expandable title="Author object fields">
            <ResponseField name="id" type="string">Author user ID.</ResponseField>
            <ResponseField name="username" type="string">Author X username.</ResponseField>
            <ResponseField name="name" type="string">Author display name.</ResponseField>
            <ResponseField name="followers" type="number">Follower count. Omitted if unavailable.</ResponseField>
            <ResponseField name="verified" type="boolean">Whether the author is verified. Omitted if unavailable.</ResponseField>
            <ResponseField name="profilePicture" type="string">Profile picture URL. Omitted if unavailable.</ResponseField>
          </Expandable>
        </ResponseField>

        <ResponseField name="media" type="object[]">
          Media attachments. Omitted when the tweet has no media.

          <Expandable title="Media object fields">
            <ResponseField name="mediaUrl" type="string">Direct media URL.</ResponseField>
            <ResponseField name="type" type="string">Media type.</ResponseField>
            <ResponseField name="url" type="string">Shortened URL from the tweet text.</ResponseField>
          </Expandable>
        </ResponseField>

        <ResponseField name="quoted_tweet" type="object">Embedded quoted tweet. Omitted if not a quote tweet.</ResponseField>
        <ResponseField name="retweeted_tweet" type="object">Original retweeted tweet. Omitted if not a retweet.</ResponseField>
      </Expandable>
    </ResponseField>

    <ResponseField name="has_next_page" type="boolean">Whether more results are available.</ResponseField>
    <ResponseField name="next_cursor" type="string">Cursor for the next page. Pass as the `cursor` query parameter.</ResponseField>

    ```json theme={null}
    {
      "tweets": [
        {
          "id": "1893456789012345678",
          "text": "Hello from a list!",
          "createdAt": "2026-03-27T10:00:00.000Z",
          "likeCount": 42,
          "retweetCount": 5,
          "viewCount": 1200,
          "author": {
            "id": "987654321",
            "username": "xquikcom",
            "name": "Xquik",
            "followers": 12400,
            "verified": true,
            "profilePicture": "https://pbs.twimg.com/profile_images/example.jpg"
          }
        }
      ],
      "has_next_page": true,
      "next_cursor": "DAACCgACGE..."
    }
    ```
  </Tab>

  <Tab title="400 Invalid list ID">
    ```json theme={null}
    { "error": "invalid_list_id", "message": "List ID required" }
    ```

    The list ID path parameter is empty.
  </Tab>

  <Tab title="401 Unauthenticated">
    ```json theme={null}
    { "error": "unauthenticated" }
    ```

    Missing or invalid API key.
  </Tab>

  <Tab title="402 Subscription required">
    ```json theme={null}
    { "error": "no_subscription" }
    ```

    No active subscription or insufficient credits. Possible error values: `no_subscription`, `subscription_inactive`, `no_credits`, `insufficient_credits`.
    For [MPP](/mpp/overview) requests without a valid payment credential, 402 returns a `WWW-Authenticate: Payment` challenge header instead.
  </Tab>

  <Tab title="404 List not found">
    ```json theme={null}
    { "error": "not_found" }
    ```

    The list could not be resolved. Check the list ID.
  </Tab>

  <Tab title="502 X API unavailable">
    ```json theme={null}
    { "error": "x_api_unavailable" }
    ```

    The read service returned an error. Retry after a short delay.
  </Tab>

  <Tab title="429 Rate Limit Exceeded">
    ```json theme={null}
    { "error": "rate_limit_exceeded", "retryAfter": 60 }
    ```

    Your tier rate limit was exceeded. Wait for the `Retry-After` header before retrying.
  </Tab>

  <Tab title="424 Dependency Failed">
    ```json theme={null}
    { "error": "x_api_unavailable" }
    ```

    The normalized v1 response contract can return 424 when the read service is unavailable.
  </Tab>
</Tabs>

<Note>
  **Related:** [List Members](/api-reference/x/list-members) · [List Followers](/api-reference/x/list-followers)
</Note>
