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

# Twitter mentions timeline API & profile alerts

> Retrieve one user's X mentions timeline with cursor pagination, time windows, author fields, engagement metrics, and media. Costs 1 credit per tweet returned.

<Panel>
  <Tabs defaultTabIndex={0} sync={false}>
    <Tab title="200" id="response-x-user-mentions-200">
      ```json theme={null}
      {
        "tweets": [],
        "has_next_page": false,
        "next_cursor": ""
      }
      ```
    </Tab>

    <Tab title="400" id="response-x-user-mentions-400">
      ```json theme={null}
      {
        "error": "invalid_input",
        "message": "Invalid input. Check the request body."
      }
      ```
    </Tab>

    <Tab title="401" id="response-x-user-mentions-401">
      ```json theme={null}
      {
        "error": "unauthenticated",
        "message": "Authentication required."
      }
      ```
    </Tab>

    <Tab title="402" id="response-x-user-mentions-402">
      ```json theme={null}
      {
        "error": "insufficient_credits",
        "message": "Insufficient credits. Top up or subscribe to continue."
      }
      ```
    </Tab>

    <Tab title="404" id="response-x-user-mentions-404">
      ```json theme={null}
      {
        "error": "user_not_found",
        "message": "X user not found. Check the username."
      }
      ```
    </Tab>

    <Tab title="424" id="response-x-user-mentions-424">
      ```json theme={null}
      {
        "error": "x_api_unavailable",
        "message": "X data source temporarily unavailable. Try again later."
      }
      ```
    </Tab>

    <Tab title="429" id="response-x-user-mentions-429">
      ```json theme={null}
      {
        "error": "rate_limit_exceeded",
        "message": "Too many requests. Try again later.",
        "retryAfter": 60
      }
      ```
    </Tab>

    <Tab title="502" id="response-x-user-mentions-502">
      ```json theme={null}
      {
        "error": "x_api_unavailable",
        "message": "X data source temporarily unavailable. Try again later."
      }
      ```
    </Tab>

    <Tab title="503" id="response-x-user-mentions-503">
      ```json theme={null}
      {
        "error": "x_api_unavailable",
        "message": "Xquik is busy right now. Retry shortly."
      }
      ```
    </Tab>
  </Tabs>
</Panel>

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

Retrieve tweets that mention one profile. Store tweet IDs, authors, timestamps,
media, engagement counts, and pagination cursors.

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

This route returns tweets that mention one X account. Use it
for brand mentions, support inboxes, lead routing, and agent handoffs. The
route is `GET /api/v1/x/users/{id}/mentions`.

<CodeGroup>
  ```bash cURL theme={null}
  # Username mentions timeline
  curl "https://xquik.com/api/v1/x/users/username/mentions" \
    -H "x-api-key: xq_your_api_key_here" | jq

  # Numeric user ID mentions timeline
  curl "https://xquik.com/api/v1/x/users/44196397/mentions" \
    -H "x-api-key: xq_your_api_key_here" | jq

  # Time-bounded mentions window
  curl -G "https://xquik.com/api/v1/x/users/username/mentions" \
    --data-urlencode "sinceTime=1777392000" \
    --data-urlencode "untilTime=1777478400" \
    -H "x-api-key: xq_your_api_key_here" | jq
  ```

  ```javascript Node.js theme={null}
  const userIdOrUsername = "username";
  let pageCursor = "";

  for (let pageIndex = 0; pageIndex < 3; pageIndex += 1) {
    const params = pageCursor === "" ? "" : `?${new URLSearchParams({ cursor: pageCursor })}`;
    const response = await fetch(
      `https://xquik.com/api/v1/x/users/${userIdOrUsername}/mentions${params}`,
      { headers: { "x-api-key": "xq_your_api_key_here" } },
    );
    const page = await response.json();
    if (!response.ok) throw new Error(JSON.stringify(page));

    const mentionRows = page.tweets.map((tweet) => ({
      mentioned_user_id_or_username: userIdOrUsername,
      tweet_id: tweet.id,
      text: tweet.text,
      tweet_url: tweet.url ?? null,
      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,
      conversation_id: tweet.conversationId ?? null,
      is_reply: tweet.isReply ?? false,
      in_reply_to_id: tweet.inReplyToId ?? null,
      like_count: tweet.likeCount ?? null,
      reply_count: tweet.replyCount ?? null,
      retweet_count: tweet.retweetCount ?? null,
      quote_count: tweet.quoteCount ?? null,
      media_urls: (tweet.media ?? []).map((item) => item.mediaUrl).filter(Boolean),
      page_index: pageIndex,
      page_cursor: pageCursor,
      next_cursor: page.next_cursor,
      has_next_page: page.has_next_page,
    }));

    for (const row of mentionRows) process.stdout.write(`${JSON.stringify(row)}\n`);

    if (!page.has_next_page || page.next_cursor === "") break;
    pageCursor = page.next_cursor;
  }
  ```

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

  user_id_or_username = "44196397"
  page_cursor = ""

  for page_index in range(3):
      params = {"cursor": page_cursor} if page_cursor else {}
      response = requests.get(
          f"https://xquik.com/api/v1/x/users/{user_id_or_username}/mentions",
          params=params,
          headers={"x-api-key": "xq_your_api_key_here"},
      )
      page = response.json()
      if not response.ok:
          raise RuntimeError(page)

      for tweet in page["tweets"]:
          mention_row = {
              "mentioned_user_id_or_username": user_id_or_username,
              "tweet_id": tweet["id"],
              "text": tweet["text"],
              "tweet_url": tweet.get("url"),
              "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"),
              "conversation_id": tweet.get("conversationId"),
              "is_reply": tweet.get("isReply", False),
              "in_reply_to_id": tweet.get("inReplyToId"),
              "like_count": tweet.get("likeCount"),
              "reply_count": tweet.get("replyCount"),
              "retweet_count": tweet.get("retweetCount"),
              "quote_count": tweet.get("quoteCount"),
              "media_urls": [
                  item["mediaUrl"]
                  for item in tweet.get("media", [])
                  if item.get("mediaUrl")
              ],
              "page_index": page_index,
              "page_cursor": page_cursor,
              "next_cursor": page["next_cursor"],
              "has_next_page": page["has_next_page"],
          }
          print(json.dumps(mention_row, separators=(",", ":")))

      if not page["has_next_page"] or not page["next_cursor"]:
          break
      page_cursor = page["next_cursor"]
  ```
</CodeGroup>

The Node.js and Python snippets write one JSON Lines row per mentioned tweet.
Store each row with the latest `next_cursor` before requesting the next page.

## Direct mention handoff

Use `GET /x/users/{id}/mentions` when a support, community, brand monitoring,
lead routing, or agent workflow needs the newest tweets mentioning one account.
This mentions timeline endpoint accepts a username or numeric user ID. It
returns one JSON page at a time. Use [`mention_extractor`](/api-reference/extractions/create)
when you need a saved extraction, estimate, or CSV, JSON, or XLSX file export.

Store `mentioned_user_id_or_username`, `tweet_id`, `text`, `tweet_url`,
`author_id`, `author_username`, `author_name`, `author_followers`, `author_verified`,
`author_profile_picture`, `created_at`, `conversation_id`, reply context,
engagement counts, media URLs, `page_cursor`, `has_next_page`, and
`next_cursor`. Treat `next_cursor` as opaque and pass it back as `cursor` only
when `has_next_page` is true. Use `sinceTime` and `untilTime` to bound a poller
window. Zero affordable results return `402 insufficient_credits`.

## Build a mentions triage job

Use these checkpoints when a support inbox, lead queue, campaign report, or
agent workflow needs mention pages for a fixed time window, with a cursor to resume.

<CardGroup cols={2}>
  <Card title="Resolve the target" icon="user-round">
    Use a username when the handle is stable, or store a numeric user ID for
    repeat jobs and warehouse joins.
  </Card>

  <Card title="Bound the window" icon="calendar-range">
    Pass `sinceTime` and `untilTime` when a poller, support queue, or campaign
    report needs a closed mention window.
  </Card>

  <Card title="Route the row" icon="git-branch">
    Store author fields, reply context, `conversation_id`, engagement counts,
    `tweet_url`, and `media_urls` for triage or scoring.
  </Card>

  <Card title="Cursor checkpoint" icon="database">
    Store `page_cursor`, `next_cursor`, and `has_next_page` before requesting
    another mentions page.
  </Card>
</CardGroup>

```json theme={null}
{
  "mentions_job_id": "brand-mentions-q2",
  "mentions_route": "GET /api/v1/x/users/{id}/mentions",
  "mentioned_user_id_or_username": "username",
  "since_time": "1777392000",
  "until_time": "1777478400",
  "cursor_param": "cursor",
  "page_cursor": "",
  "next_cursor": "DAACCgACGRElMJcAAA",
  "has_next_page": true,
  "saved_export_tool": "mention_extractor"
}
```

| Mention queue column | Response source | Triage use |
| - | - | - |
| `mentioned_x_user_id` | Resolved target profile ID | Keep every mention tied to the intended account. |
| `tweet_id` | `tweets[].id` | Deduplicate mentions and open one source tweet. |
| `tweet_url` | `tweets[].url` | Send reviewers to the original X post. |
| `text` | `tweets[].text` | Apply support, lead, campaign, or moderation rules. |
| `author_id` | `tweets[].author.id` | Keep a stable mention-author key. |
| `author_username` | `tweets[].author.username` | Display the current author handle. |
| `author_followers` | `tweets[].author.followers` | Add audience context to priority rules. |
| `author_verified` | `tweets[].author.verified` | Keep the observed verification state. |
| `created_at` | `tweets[].createdAt` | Enforce the intended support or campaign window. |
| `conversation_id` | `tweets[].conversationId` | Group mention tweets from one conversation. |
| `in_reply_to_id` | `tweets[].inReplyToId` | Join reply mentions to their immediate parent. |
| `media_urls` | `tweets[].media[].mediaUrl` | Keep image and video context for review. |

| Mention rule | Concrete condition | Queue action |
| - | - | - |
| Direct support request | Approved support phrase in `text` | Create a support-review item. |
| Campaign mention | Campaign phrase within `sinceTime` and `untilTime` | Add the tweet to the campaign report. |
| High-reach author | Approved `author.followers` threshold | Raise the review priority. |
| Reply in an existing thread | Non-empty `inReplyToId` or `conversationId` | Attach the existing conversation context. |
| Media evidence | Non-empty `media` | Keep image or video URLs with the triage record. |
| No approved rule | No explicit rule matches | Store the mention with no category. |

## Which timeline endpoint?

* Use `GET /api/v1/x/users/{id}/mentions` for one user's mentions timeline.
* Use `GET /api/v1/x/users/{id}/tweets` for one user's profile timeline.
* Use `GET /api/v1/x/tweets/search` for keyword, operator, or advanced search.
* Use `GET /api/v1/x/timeline` for the authenticated account's home timeline.

## Path parameters

<ParamField path="id" type="string" required>
  User ID, username with or without `@`, or URL-encoded profile URL, such as
  `x.com/nasa`. See [path IDs](/api-reference/overview#path-ids).
</ParamField>

## Query parameters

<ParamField query="cursor" type="string">
  Pagination cursor for the mentions timeline. Omit it for the first page, then
  pass the `next_cursor` value from the previous response to fetch the next
  page.
</ParamField>

<ParamField query="pageSize" type="integer">
  Tweets per page. Range: `1-100`. Defaults to `20`.
</ParamField>

<ParamField query="sinceTime" type="string">
  Unix timestamp in seconds. Only return mentions after this time when a poller,
  support inbox, or campaign monitor needs a bounded window.
</ParamField>

<ParamField query="untilTime" type="string">
  Unix timestamp in seconds. Only return mentions before this time. Pair with
  `sinceTime` for closed reporting windows.
</ParamField>

### Tweet result filters

These optional filters apply to `tweets[]` returned by this route. They keep the
same mentions target. Xquik filters rows after it fetches each page. Selective
filters can return fewer rows than an unfiltered page.

<ParamField query="fromUser" type="string">
  Filter to posts from this username. The `@` prefix is optional.
</ParamField>

<ParamField query="toUser" type="string">
  Filter to replies directed to this username.
</ParamField>

<ParamField query="mentioning" type="string">
  Filter to posts that mention this username.
</ParamField>

<ParamField query="language" type="string">
  Only include posts with this language code.
</ParamField>

<ParamField query="sinceDate" type="string">
  Include posts created on or after this date or timestamp.
</ParamField>

<ParamField query="untilDate" type="string">
  Include posts up to this date or timestamp. A date is a UTC day, inclusive, so its own posts count.
</ParamField>

<ParamField query="mediaType" type="string">
  Use `images`, `videos`, `gifs`, `media`, `links`, or `none`.
</ParamField>

<ParamField query="minLikes" type="integer">
  Require this minimum like count.
</ParamField>

<ParamField query="minRetweets" type="integer">
  Require this minimum repost count.
</ParamField>

<ParamField query="minReplies" type="integer">
  Require this minimum reply count.
</ParamField>

<ParamField query="minQuotes" type="integer">
  Require this minimum quote count.
</ParamField>

<ParamField query="minViews" type="integer">
  Require this minimum view count.
</ParamField>

<ParamField query="minBookmarks" type="integer">
  Require this minimum bookmark count.
</ParamField>

<ParamField query="maxFaves" type="integer">
  Allow this maximum like count. Missing counts pass.
</ParamField>

<ParamField query="maxRetweets" type="integer">
  Allow this maximum repost count. Missing counts pass.
</ParamField>

<ParamField query="maxReplies" type="integer">
  Allow this maximum reply count. Missing counts pass.
</ParamField>

<ParamField query="maxQuotes" type="integer">
  Allow this maximum quote count. Missing counts pass.
</ParamField>

<ParamField query="blueVerifiedOnly" type="boolean">
  When `true`, only return posts from Blue-verified authors.
</ParamField>

<ParamField query="verifiedOnly" type="boolean">
  When `true`, only return posts from verified authors.
</ParamField>

<ParamField query="replies" type="string">
  Use `include`, `exclude`, or `only` for replies.
  This setting overrides `includeReplies` when the endpoint supports both.
</ParamField>

<ParamField query="retweets" type="string">
  Use `include`, `exclude`, or `only` for reposts.
</ParamField>

<ParamField query="exactPhrase" type="string">
  Match this literal phrase, including any hyphens.
</ParamField>

<ParamField query="excludeWords" type="string">
  Exclude comma-separated or whitespace-separated terms.
</ParamField>

<ParamField query="anyWords" type="string">
  Require at least 1 comma-separated or whitespace-separated term.
</ParamField>

<ParamField query="hashtags" type="string">
  Match these hashtags. Separate values with commas or spaces.
</ParamField>

<ParamField query="cashtags" type="string">
  Match these cashtags. Separate values with commas or spaces.
</ParamField>

<ParamField query="quotes" type="string">
  Use `include`, `exclude`, or `only` for quote posts.
</ParamField>

<ParamField query="url" type="string">
  URL substring or domain that must appear in tweet URL entities.
</ParamField>

<ParamField query="conversationId" type="string">
  Filter to tweets in this conversation thread.
</ParamField>

<ParamField query="inReplyToTweetId" type="string">
  Only include replies to this tweet ID.
</ParamField>

<ParamField query="quotesOfTweetId" type="string">
  Filter to quote tweets of this tweet ID.
</ParamField>

<ParamField query="retweetsOfTweetId" type="string">
  Filter to retweets of this tweet ID.
</ParamField>

<ParamField query="sinceId" type="string">
  Return Tweets whose IDs exceed this ID.
</ParamField>

<ParamField query="maxId" type="string">
  Return Tweets at or below this ID.
</ParamField>

<ParamField query="nativeRetweets" type="boolean">
  When `true`, only return native reposts.
</ParamField>

<ParamField query="withinTime" type="string">
  Match Tweets from this recent window, such as `90m` or `7d`. Use a whole number & `s`, `m`, `h` or `d`.
</ParamField>

## Headers

<ParamField header="x-api-key" type="string">
  Full account key. Sessions and OAuth also work.
</ParamField>

<ParamField header="Authorization" type="string">
  `Bearer xq_your_guest_key_here` for `paid_reads`.
</ParamField>

## Response

### 200 OK

<ResponseField name="tweets" type="object[]">
  Array of tweets mentioning the user.
  **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="isPinned" type="boolean">Whether the author pinned this post to their profile. 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="isRetweet" type="boolean">Whether this row is a retweet. `text` carries the original post in full.</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.
    **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>
  </ResponseField>

  <ResponseField name="media" type="object[]">
    Media attachments. Omitted when the tweet has no media.
    **Media object fields.**
    <ResponseField name="mediaUrl" type="string">Direct media URL.</ResponseField>
    <ResponseField name="videoVariants" type="object[]">Available video renditions with bitrate, content type, and URL. Omitted for images.</ResponseField>
    <ResponseField name="type" type="string">Media type.</ResponseField>
    <ResponseField name="url" type="string">Shortened URL from the tweet text.</ResponseField>
  </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>
</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.</ResponseField>

```json theme={null}
{
  "tweets": [
    {
      "id": "1893456789012345678",
      "text": "Hey @user check this out!",
      "createdAt": "2026-03-27T10:00:00.000Z",
      "likeCount": 5,
      "author": {
        "id": "987654321",
        "username": "customer",
        "name": "Customer",
        "followers": 4200,
        "verified": false,
        "profilePicture": "https://pbs.twimg.com/profile_images/customer/photo.jpg"
      }
    }
  ],
  "has_next_page": true,
  "next_cursor": "DAACCgACGE..."
}
```

### 400 Invalid user ID

```json theme={null}
{
  "error": "invalid_user_id",
  "message": "Send a user ID, @username or profile URL, such as x.com/nasa."
}
```

### 404 User not found

```json theme={null}
{ "error": "user_not_found", "message": "X user not found. Check the username." }
```

### 401 Unauthenticated

Anonymous requests get `WWW-Authenticate: Bearer` and a guest wallet checkout action. This is not a Payment challenge.

```json theme={null}
{ "error": "unauthenticated" }
```

### 402 Payment required

Account keys get account options. Guest keys get guest top-up only.
No checkout starts automatically. Confirm any payment action.

### 502 X API unavailable

```json theme={null}
{ "error": "x_api_unavailable" }
```

The read service returned an error. Retry after a short delay.

### 429 Rate limit exceeded

```json theme={null}
{ "error": "rate_limit_exceeded", "retryAfter": 60 }
```

You exceeded your tier rate limit. Wait for the `Retry-After` header before retrying.

### 424 Dependency failed

```json theme={null}
{ "error": "x_api_unavailable" }
```

The normalized v1 response contract can return 424 when the read service is unavailable.

<Note>
  **Related.** [Get user timeline](/api-reference/x/user-tweets) · [User media](/api-reference/x/user-media) · [User likes](/api-reference/x/user-likes)
</Note>

<div className="related-api-links">
  <Accordion title="Related timeline, bookmark & notification APIs" icon="link">
    * Account feeds: [Home timeline](/api-reference/x/timeline) · [Notifications](/api-reference/x/notifications) · [Mentions](/api-reference/x/user-mentions)
    * Saved and private: [Bookmarks](/api-reference/x/bookmarks) · [Bookmark folders](/api-reference/x/bookmark-folders) · [DM history](/api-reference/x/dm-history)
  </Accordion>
</div>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.