> ## 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 brand monitoring API for X mentions with AI

> Monitor brand mentions on X with AI. Get each post's relevance, attitude toward your brand, and customer relationship. Costs 2 credits per analyzed post.

<Panel>
  <Tabs defaultTabIndex={0} sync={false}>
    <Tab title="200" id="response-x-brand-monitoring-200">
      ```json theme={null}
      {
        "results": [
          {
            "tweet": {
              "id": "1893456789012345678",
              "text": "The new headphones sound great. The app keeps crashing.",
              "retweetCount": 4,
              "replyCount": 2,
              "likeCount": 31
            },
            "analysis": {
              "status": "succeeded",
              "answers": [
                {
                  "questionId": "sentiment",
                  "questionVersion": "sentiment:2",
                  "type": "choice",
                  "value": "mixed",
                  "confidence": 0.88
                }
              ],
              "questions": [
                {
                  "id": "sentiment",
                  "version": "sentiment:2"
                }
              ],
              "contextBytes": 612,
              "contextAvailability": {
                "quote": "not_applicable",
                "reply": "not_applicable",
                "author": "available",
                "media": "not_supplied",
                "article": "not_supplied"
              }
            },
            "answers": {
              "sentiment": "mixed",
              "intensity": 1,
              "sarcasm": 0.03
            },
            "sourceDomains": [],
            "cashtags": []
          }
        ],
        "unanalyzed": [
          {
            "id": "1893456789012345679",
            "status": "skipped",
            "reason": "post_unavailable"
          }
        ],
        "analysisSummary": {
          "schemaVersion": 1,
          "rows": {
            "analyzed": 1,
            "failed": 0,
            "skipped": 0
          },
          "engagement": 37,
          "questions": {
            "sentiment": {
              "type": "choice",
              "counts": {
                "positive": 0,
                "negative": 0,
                "mixed": 1,
                "neutral": 0,
                "unclear": 0
              },
              "shares": {
                "positive": 0,
                "negative": 0,
                "mixed": 1,
                "neutral": 0,
                "unclear": 0
              }
            }
          },
          "targets": []
        },
        "has_next_page": false,
        "next_cursor": ""
      }
      ```
    </Tab>

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

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

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

    <Tab title="403" id="response-x-brand-monitoring-403">
      ```json theme={null}
      {
        "error": "x_account_protected",
        "message": "Account is protected. Choose a public account."
      }
      ```
    </Tab>

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

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

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

    <Tab title="503" id="response-x-brand-monitoring-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>

<Callout icon="coins" color="#5c3327">
  **2 credits per analyzed post** · [All plans](https://xquik.com/#pricing) from \$0.00012/credit · Supports [guest paid reads](/guides/guest-wallets)
</Callout>

Brand monitoring reads each post with AI and answers 3 questions about your
brand. The endpoint is `POST /api/v1/x/analysis/brand`.

| Answer | Type | Values |
| - | - | - |
| `relevance` | Probability | From `0` to `1`, the chance the post discusses your brand |
| `sentiment` | Choice | `positive`, `negative`, `mixed`, `neutral`, or `unclear` |
| `experience` | Choice | `customer`, `prospect`, `observer`, or `unclear` |

Name the brand in `analysis.targets`, with its products and handles as aliases.

<CodeGroup>
  ```bash cURL theme={null}
  curl -X POST https://xquik.com/api/v1/x/analysis/brand \
    -H "x-api-key: xq_your_api_key_here" \
    -H "Content-Type: application/json" \
    -d '{
      "query": "(Sony OR WH-1000XM6) headphones lang:en -filter:nativeretweets",
      "limit": 50,
      "analysis": {
        "targets": [{ "name": "Sony", "aliases": ["WH-1000XM6", "@Sony"] }],
        "context": "Consumer headphones & customer service."
      }
    }' | jq
  ```

  ```javascript Node.js theme={null}
  const response = await fetch("https://xquik.com/api/v1/x/analysis/brand", {
    method: "POST",
    headers: {
      "x-api-key": "xq_your_api_key_here",
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      query: "(Sony OR WH-1000XM6) headphones lang:en -filter:nativeretweets",
      limit: 50,
      analysis: {
        targets: [{ name: "Sony", aliases: ["WH-1000XM6", "@Sony"] }],
        context: "Consumer headphones & customer service.",
      },
    }),
  });
  const data = await response.json();
  if (!response.ok) throw new Error(`${data.error}: ${data.message}`);

  const unhappyCustomers = data.results
    .filter((result) => result.answers.relevance >= 0.5)
    .filter((result) => result.answers.sentiment === "negative")
    .filter((result) => result.answers.experience === "customer")
    .map((result) => ({ tweet_id: result.tweet.id, text: result.tweet.text }));
  const brand = data.analysisSummary.targets[0];

  process.stdout.write(
    `${JSON.stringify({ mentions: brand?.mentions, sentiment: brand?.choices.sentiment, unhappyCustomers })}\n`,
  );
  ```

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

  response = requests.post(
      "https://xquik.com/api/v1/x/analysis/brand",
      headers={"x-api-key": "xq_your_api_key_here"},
      json={
          "query": "(Sony OR WH-1000XM6) headphones lang:en -filter:nativeretweets",
          "limit": 50,
          "analysis": {
              "targets": [{"name": "Sony", "aliases": ["WH-1000XM6", "@Sony"]}],
              "context": "Consumer headphones & customer service.",
          },
      },
      timeout=120,
  )
  data = response.json()
  if not response.ok:
      raise RuntimeError(f"{data['error']}: {data['message']}")

  unhappy_customers = [
      {"tweet_id": result["tweet"]["id"], "text": result["tweet"]["text"]}
      for result in data["results"]
      if result["answers"]["relevance"] >= 0.5
      and result["answers"]["sentiment"] == "negative"
      and result["answers"]["experience"] == "customer"
  ]
  targets = data["analysisSummary"]["targets"]
  brand = targets[0] if targets else {}
  print(json.dumps({
      "mentions": brand.get("mentions"),
      "sentiment": brand.get("choices", {}).get("sentiment"),
      "unhappy_customers": unhappy_customers,
  }))
  ```
</CodeGroup>

The snippets list unhappy customers and print the brand's totals. They do not
print the full response.

## Name the brand

Put the brand in `analysis.targets`, with product names, handles, and common
misspellings as aliases. Add `analysis.context` when the name has other
meanings, such as a fruit or a city.

```json theme={null}
{ "name": "Sony", "aliases": ["WH-1000XM6", "@Sony", "@SonyElectronics"] }
```

`relevance` is low for namesakes and posts that only share a word with the
brand. Filter rows on `relevance` before you count answers. The snippets keep
posts from `0.5`.

## Read the brand answers

`results[].answers` holds each decision by question ID.

| `sentiment` | Meaning |
| - | - |
| `positive` | Praise or a positive experience |
| `negative` | Dissatisfaction, criticism, or negative sarcasm |
| `mixed` | Both positive and negative judgments |
| `neutral` | Information without a judgment |
| `unclear` | The brand or the attitude cannot be established |

`sentiment` judges the attitude toward your brand, not the post's general mood.

| `experience` | Meaning |
| - | - |
| `customer` | Describes their own purchase or service experience |
| `prospect` | Considers a purchase or asks for recommendations |
| `observer` | Discusses the brand without a personal transaction |
| `unclear` | Not enough context |

Negative posts from customers are the support queue. Posts from prospects are
sales leads.

## Track a brand over time

`analysisSummary.targets` holds each target's `mentions`, its `share` of posts,
its `engagement`, its category counts in `choices`, and the most engaged posts
per category in `top`. Store it per run to chart a trend.

Name each competitor as its own target to compare brands in 1 call. For more
posts than 1 call returns, send the same body again with `cursor` set to
`next_cursor`.

## Monitor replies & quotes

Send `repliesTo` with a launch post's URL to read the replies to it. Send
`quotesOf` to read its quotes. Send `username` to read 1 account's posts, such
as a competitor's support account.

```json theme={null}
{
  "repliesTo": "https://x.com/Sony/status/1893456789012345678",
  "analysis": { "targets": [{ "name": "Sony" }] }
}
```

## Use another brand preset

Set `analysis.preset` to ask other ready questions about your brand, at the
same price. Each needs `analysis.targets`.

| Preset | Answers |
| - | - |
| `complaints` | `complaint`, the `issue` category, and `urgency` |
| `competitors` | The `event`, such as a launch or a price change, `firsthand`, and `commercial_relevance` |
| `purchase_intent` | `intent`, `fit`, and `readiness` to buy |
| `product_feedback` | `feedback`, such as a defect or a feature request, `firsthand_use`, and `impact` |

## Pick the posts to analyze

Send `tweetIds`, `texts`, or a search, never more than 1. Sending none, or more
than 1, returns `400 invalid_input`.

| Source | Send | Posts analyzed |
| - | - | - |
| Post IDs | `tweetIds`, up to 100 post IDs or post URLs | Each post once |
| Your own texts | `texts`, up to 100 strings | Each text. Reads nothing from X |
| A search | 1 or more of the search fields below | Up to `limit` posts, 20 by default |

A search combines every search field you send into 1 X search.

| Search field | Posts it finds |
| - | - |
| `query` | An X search, with the operators of [Search Tweets](/api-reference/x/search-tweets) |
| `username` | 1 account's posts. A handle, `@handle`, or profile URL |
| `listId` | A public List's posts. A List ID or URL |
| `quotesOf` | The quotes of 1 post. A post ID or URL |
| `repliesTo` | The replies in 1 post's conversation. A post ID or URL |
| `sinceTime` & `untilTime` | Posts between 2 times. An ISO 8601 time or Unix seconds |

`queryType` sets the order, `Latest` or `Top`. For more posts than 1 call
returns, send the same search again with `cursor` set to `next_cursor`. Stop
when `has_next_page` is `false`.

```json theme={null}
{
  "username": "NASA",
  "sinceTime": "2026-09-25T00:00:00Z",
  "untilTime": "2026-09-26T00:00:00Z"
}
```

## Compare with an earlier answer

Send the `results` of an earlier call as `baseline` to see what changed. Each
row in the new `results` gets `monitor`, and `analysisSummary.monitor` counts
the posts per status. The comparison costs nothing extra.

```json theme={null}
{
  "query": "Sony WH-1000XM6 lang:en",
  "baseline": [
    { "id": "1893456789012345678", "answers": { "sentiment": "positive", "intensity": 1.2 } }
  ]
}
```

A baseline row needs the post's `id`, or `tweet.id`, and its `answers`. Send
whole result rows when you have them. Their `monitor` carries the settings'
fingerprint, so rows from other settings show as `not_comparable`.

| `monitor.status` | Meaning |
| - | - |
| `first_run` | You sent no baseline |
| `new_to_baseline` | The baseline has no row for this post |
| `unchanged` | Every decision matches the baseline |
| `changed` | At least 1 decision clearly moved. `changes` lists each 1 |
| `not_comparable` | Other settings made the row, or it answers none of these questions |

A decision counts as changed only when the new answer clearly leaves the old
one, so near ties between calls stay `unchanged`. Keep `analysis` the same
between calls for comparable answers.

## Budget the analysis

Each analyzed post costs 2 credits. Each text in `texts` costs the same. Posts
in `unanalyzed` cost nothing.

When credits cover fewer posts than you asked for, fewer come back. The posts
left over appear in `unanalyzed` with `insufficient_credits`. If credits cover
no post, the call returns `402 insufficient_credits`.

| `unanalyzed[].reason` | Meaning | What to do |
| - | - | - |
| `post_unavailable` | X returns no such post | Skip the post |
| `missing_text` | The post has no text | Skip the post |
| `insufficient_credits` | Credits ran out | Add credits, then send it again |
| `context_limit` | The settings leave the post no room | Shorten the context or questions |
| Any other reason | The analysis failed (`status: "failed"`) | Send the post again |

## Body

<ParamField body="tweetIds" type="string[]">
  Up to 100 post IDs or post URLs, such as `x.com/nasa/status/20`. A post named
  twice is analyzed once. Send `tweetIds`, `texts`, or a search, not more than 1.
</ParamField>

<ParamField body="query" type="string">
  X search to analyze, with the operators of [Search Tweets](/api-reference/x/search-tweets).
</ParamField>

<ParamField body="username" type="string">
  Analyze 1 account's posts. Send a handle, with or without `@`, or a profile URL.
</ParamField>

<ParamField body="listId" type="string">
  Analyze a public List's posts. Send its ID or URL.
</ParamField>

<ParamField body="quotesOf" type="string">
  Analyze the quotes of 1 post. Send its ID or URL.
</ParamField>

<ParamField body="repliesTo" type="string">
  Analyze the replies in 1 post's conversation. Send its ID or URL.
</ParamField>

<ParamField body="sinceTime" type="string">
  Inclusive start of the search, such as `2026-09-25T00:00:00Z`. Unix seconds
  also work. A time without an offset is UTC.
</ParamField>

<ParamField body="untilTime" type="string">
  Exclusive end of the search. Unix seconds also work. A time without an offset
  is UTC.
</ParamField>

<ParamField body="queryType" type="string">
  Search order: `Latest` or `Top`. Defaults to `Latest`.
</ParamField>

<ParamField body="limit" type="integer">
  Maximum posts to analyze from the search. Range: `1-100`. Defaults to `20`.
  Credits can return fewer.
</ParamField>

<ParamField body="cursor" type="string">
  The `next_cursor` of the page before. Send the same search with it.
</ParamField>

<ParamField body="texts" type="string[]">
  Up to 100 texts of your own, such as drafts. Each must contain words. Reads
  nothing from X.
</ParamField>

<ParamField body="baseline" type="object[]">
  Rows of an earlier answer to compare with, up to 10,000, such as its
  `results`. Each needs the post's `id`, or `tweet.id`, and its `answers`. Each
  new result's `monitor` says whether the post is new, changed, or unchanged.
  The comparison costs nothing extra.
</ParamField>

<ParamField body="analysis" type="object">
  Optional settings. Leave it out to ask the route's own questions.

  <Expandable title="Analysis fields">
    <ParamField body="targets" type="object[]">
      Up to 100 brands, people, assets, or topics the questions are about. Each
      has a `name` and optional `aliases`, such as a ticker or product name.
    </ParamField>

    <ParamField body="context" type="string">
      Background the AI reads with every post, such as your product or market.
    </ParamField>

    <ParamField body="questions" type="object[]">
      1 to 8 questions of your own, which replace the route's questions. Each
      needs an `id`, a `type` of `choice`, `score`, or `probability`, a
      `version`, and `instructions`. A choice adds `categories`, a score adds
      `levels`, and a probability can add `criteria`.
    </ParamField>

    <ParamField body="preset" type="string">
      A ready set of questions, used when `questions` is left out: `brand`,
      `complaints`, `competitors`, `purchase_intent`, `product_feedback`,
      `news`, `sentiment`, or `market`. `complaints`, `competitors`,
      `purchase_intent`, and `product_feedback` need `targets`.
    </ParamField>

    <ParamField body="maxContextBytes" type="integer">
      Bytes of post, quote, and settings the AI reads. Range: `1-64000`.
      Defaults to `64000`. Xquik cuts a longer post to fit.
    </ParamField>

    <ParamField body="concurrency" type="integer">
      Posts analyzed at the same time. Range: `1-16`. Defaults to `16`.
    </ParamField>
  </Expandable>
</ParamField>

## Headers

<ParamField header="x-api-key" type="string">
  Full account API key. An OAuth bearer token also works.
</ParamField>

<ParamField header="Authorization" type="string">
  Send `Bearer xq_your_guest_key_here` for an active `paid_reads` guest key.
</ParamField>

<ParamField header="Content-Type" type="string" required>
  Must be `application/json`. The body can be up to 256 KB.
</ParamField>

## Response

### 200 OK

<ResponseField name="results" type="object[]">
  Each analyzed post with its answers. Each row costs 2 credits.

  <Expandable title="Result fields">
    <ResponseField name="tweet" type="object">
      The post, as [Search Tweets](/api-reference/x/search-tweets) returns it. Your own texts have the IDs `text:1`, `text:2`, and so on.
    </ResponseField>

    <ResponseField name="answers" type="object">
      Each decision by question ID. `sentiment` and `experience` are categories, and `relevance` a probability from `0` to `1`.
    </ResponseField>

    <ResponseField name="analysis" type="object">
      The answers in full. `status` is `succeeded`. `answers` gives each answer's `value`, `confidence`, and `probabilities`, or a `probability`. `questions` names the ID and version of each question. `contextBytes` and `contextAvailability` say what the AI read beside the post's text.
    </ResponseField>

    <ResponseField name="sourceDomains" type="string[]">
      Hostnames the post links to, without `t.co`.
    </ResponseField>

    <ResponseField name="cashtags" type="string[]">
      Cashtags in the post's text, in upper case.
    </ResponseField>

    <ResponseField name="monitor" type="object">
      The comparison with `baseline`: `status`, `changedQuestionIds`, `changes` with each `previous` and `current` decision, and the settings' `configurationFingerprint`.
    </ResponseField>
  </Expandable>
</ResponseField>

<ResponseField name="unanalyzed" type="object[]">
  Each post without an analysis. These cost nothing.

  <Expandable title="Unanalyzed fields">
    <ResponseField name="id" type="string">
      Post ID, or `text:1` and so on for your own texts.
    </ResponseField>

    <ResponseField name="status" type="string">
      `skipped` or `failed`.
    </ResponseField>

    <ResponseField name="reason" type="string">
      `post_unavailable`, `missing_text`, `insufficient_credits`, or `context_limit`. Any other reason means the analysis failed. Send the post again.
    </ResponseField>
  </Expandable>
</ResponseField>

<ResponseField name="analysisSummary" type="object">
  Totals of the answers across the analyzed posts.

  <Expandable title="Summary fields">
    <ResponseField name="schemaVersion" type="integer">
      Version of the summary's shape.
    </ResponseField>

    <ResponseField name="rows" type="object">
      Posts by outcome: `analyzed`, `failed`, and `skipped`.
    </ResponseField>

    <ResponseField name="engagement" type="integer">
      Likes, reposts, replies, and quotes of the analyzed posts.
    </ResponseField>

    <ResponseField name="questions" type="object">
      Totals by question ID. `sentiment` and `experience` have `counts`, `shares`, `engagementShares`, and `top` posts per category. `relevance` has `mean`, `yes`, and `no`.
    </ResponseField>

    <ResponseField name="targets" type="object[]">
      Per target in `analysis.targets`: `name`, `mentions`, `share`, `engagement`, `choices`, and `top` posts.
    </ResponseField>

    <ResponseField name="cashtags" type="object[]">
      Posts and category counts per cashtag, most posts first, up to 20.
    </ResponseField>

    <ResponseField name="sourceDomains" type="object[]">
      Posts per linked hostname, most posts first, up to 20.
    </ResponseField>

    <ResponseField name="monitor" type="object">
      Posts per `monitor.status` in `statuses`, and up to 50 changed posts in `changedRows`.
    </ResponseField>
  </Expandable>
</ResponseField>

<ResponseField name="has_next_page" type="boolean">Whether the search has more posts. Always `false` for `tweetIds` and `texts`.</ResponseField>
<ResponseField name="next_cursor" type="string">Send it as `cursor` with the same search for the next page. Empty when there is none.</ResponseField>

```json theme={null}
{
  "results": [
    {
      "tweet": {
        "id": "1893456789012345678",
        "text": "My WH-1000XM6 stopped pairing after the update. Sony support has not replied in 3 days.",
        "likeCount": 48,
        "retweetCount": 6,
        "replyCount": 11
      },
      "analysis": {
        "status": "succeeded",
        "answers": [
          {
            "questionId": "relevance",
            "questionVersion": "brand:2",
            "type": "probability",
            "probability": 0.98
          },
          {
            "questionId": "sentiment",
            "questionVersion": "brand:2",
            "type": "choice",
            "value": "negative",
            "confidence": 0.95,
            "probabilities": {
              "positive": 0.01,
              "negative": 0.95,
              "mixed": 0.02,
              "neutral": 0.01,
              "unclear": 0.01
            }
          },
          {
            "questionId": "experience",
            "questionVersion": "brand:2",
            "type": "choice",
            "value": "customer",
            "confidence": 0.93,
            "probabilities": {
              "customer": 0.93,
              "prospect": 0.02,
              "observer": 0.04,
              "unclear": 0.01
            }
          }
        ]
      },
      "answers": { "relevance": 0.98, "sentiment": "negative", "experience": "customer" },
      "sourceDomains": [],
      "cashtags": []
    }
  ],
  "unanalyzed": [],
  "analysisSummary": {
    "schemaVersion": 1,
    "rows": { "analyzed": 1, "failed": 0, "skipped": 0 },
    "engagement": 65,
    "questions": {
      "sentiment": {
        "type": "choice",
        "counts": { "positive": 0, "negative": 1, "mixed": 0, "neutral": 0, "unclear": 0 }
      }
    },
    "targets": [
      {
        "name": "Sony",
        "mentions": 1,
        "share": 1,
        "engagement": 65,
        "choices": { "sentiment": { "negative": 1 }, "experience": { "customer": 1 } },
        "top": {
          "sentiment": { "negative": [{ "tweetId": "1893456789012345678", "engagement": 65 }] }
        }
      }
    ],
    "cashtags": [],
    "sourceDomains": []
  },
  "has_next_page": false,
  "next_cursor": ""
}
```

### 400 Invalid input

```json theme={null}
{
  "error": "invalid_input",
  "message": "Send only 1 of tweetIds, texts & a search such as query or username."
}
```

The body names no posts, names more than 1 source, or has an invalid field.
The message says what to send instead. The request costs nothing.

### 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" }
```

Missing or invalid API key. Check the `x-api-key` header value.

### 402 Payment required

Full account keys can receive `no_subscription`, `subscription_inactive`, `no_credits`, or `insufficient_credits` with account payment options. Guest keys receive only the guest top-up action.

The failed request creates no checkout. Ask the user to confirm before calling any checkout or top-up route.

### 403 Protected account

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

A search that needs a protected author returns this. Choose a public account.
The request costs nothing.

### 502 X API unavailable

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

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

### 503 Service busy

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

Xquik is busy. Wait for the `Retry-After` header, then send the request again.
The request costs nothing.

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

## Brand monitoring API questions

### How do I monitor brand mentions on X?

Search the brand's names in `query` and name the brand in `analysis.targets`.
Each row in `results` holds the post and its `relevance`, `sentiment`, and
`experience` answers.

### How do I find customers who need help?

Keep rows whose `sentiment` is `negative` and whose `experience` is `customer`.
For the problem and its urgency, set `analysis.preset` to `complaints`.

### Can I compare my brand with competitors?

Yes. Name each brand as its own target. `analysisSummary.targets` counts the
mentions and sentiment of each one.

### Does it skip posts about namesakes?

The AI answers `relevance` for every post. A namesake, such as a person who
shares the brand's name, gets a low `relevance`. Filter on it.

### How much does brand monitoring cost?

Each analyzed post costs 2 credits. Posts in `unanalyzed` and refused requests
cost nothing.

### Does this replace X's official API?

No. This page documents Xquik, an independent third-party service.
It does not document X's official API.

<Note>
  **Next steps.** [Sentiment analysis](/api-reference/x/sentiment-analysis) reads the attitude of any post, or [Classify posts](/api-reference/x/classify-tweets) asks your own questions.
</Note>

<div className="related-api-links">
  <Accordion title="Related tweet, reply & media APIs" icon="link">
    * Tweets: [Get tweet](/api-reference/x/get-tweet) · [Batch tweets](/api-reference/x/batch-tweets) · [Tweet thread](/api-reference/x/tweet-thread) · [Hidden replies](/api-reference/x/tweet-hidden-replies) · [Translate tweet](/api-reference/x/tweet-translation) · [Embed tweet](/api-reference/x/tweet-embed) · [Resolve links](/api-reference/x/resolve-links) · [Tweet subtitles](/api-reference/x/tweet-subtitles) · [X Article](/api-reference/x/get-article)
    * Analysis: [Sentiment analysis](/api-reference/x/sentiment-analysis) · [Brand mentions](/api-reference/x/brand-monitoring) · [News classification](/api-reference/x/news-classification) · [Market signals](/api-reference/x/market-signals) · [Viral score](/api-reference/x/viral-score) · [Classify posts](/api-reference/x/classify-tweets)
    * Engagement: [Tweet replies](/api-reference/x/tweet-replies) · [Quote tweets](/api-reference/x/tweet-quotes) · [Likers](/api-reference/x/favoriters) · [Reposters](/api-reference/x/retweeters) · [Check repost](/api-reference/x/tweet-repost-check)
    * Profiles: [User tweets](/api-reference/x/user-tweets) · [Batch user tweets](/api-reference/x/batch-user-tweets) · [User replies](/api-reference/x/user-replies) · [User likes](/api-reference/x/user-likes) · [User media](/api-reference/x/user-media) · [User highlights](/api-reference/x/user-highlights) · [User articles](/api-reference/x/user-articles)
    * Feeds: [List tweets](/api-reference/x/list-tweets) · [Trends](/api-reference/x/trends) · [Trend locations](/api-reference/x/trend-locations) · [Search Spaces](/api-reference/x/search-spaces) · [Get Space](/api-reference/x/get-space) · [Space replay](/api-reference/x/space-replay) · [Get broadcast](/api-reference/x/get-broadcast) · [Hashflags](/api-reference/x/hashflags) · [Search places](/api-reference/x/search-places) · [Download media](/api-reference/x/download-media)
  </Accordion>
</div>


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