> ## 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 account monitoring list & tracked profiles

> List Twitter account monitors with tracked X profiles, tweet and profile event filters, active states, creation times, and billing checkpoints per monitor.

<Panel>
  <Tabs defaultTabIndex={0} sync={false}>
    <Tab title="200" id="response-monitors-list-200">
      ```json theme={null}
      {
        "monitors": [],
        "total": 0,
        "hasMore": false
      }
      ```
    </Tab>

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

    <Tab title="401" id="response-monitors-list-401">
      ```json theme={null}
      {
        "error": "unauthenticated",
        "message": "Authentication required. Provide a valid API key or bearer token."
      }
      ```
    </Tab>

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

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

## Inventory every Twitter account monitor

Use `GET /monitors` when you monitor multiple Twitter accounts.
It returns up to 200 account monitors in one response.
The route lists only monitors that belong to the signed-in user. Each
row identifies one tracked X profile. It also shows enabled tweet or profile
events and the active state. The row includes its creation time. Check
`nextBillingAt` for the next active-monitor charge. Use the single-monitor
route for one known ID.

Group rows by `username` or stable `xUserId`. Keep `eventTypes` with every row
because two monitors can track different changes. Separate inactive monitors
before calculating which profiles still produce events.

Store `monitorId` before handing a row to event or webhook processing. Event
queries use that ID to isolate tweets and profile changes. Webhook deliveries
remain separate from monitor inventory.

Review `nextBillingAt` before enabling more monitors. Listing is free, but
active monitors consume credits each hour. Delete unused monitors. Do not call
a monitor idle after one empty event window.

<Callout icon="circle-check" color="#16a34a">
  **Free.** This endpoint does not consume credits.
</Callout>

## How do you monitor multiple Twitter accounts?

Create one account monitor for each X username. Select only the required tweet
and profile event types. Then call this route to rebuild the complete list.
Store each returned `id` as the stable monitor key. Keep `xUserId` beside the
username because an account can change its username.

Use `isActive` to filter rows before estimating costs.
Group active rows by owner, workflow, or webhook receiver. Keep paused rows in
the same inventory because their configuration still exists.

Use [List Events](/api-reference/events/list) to retrieve stored events for one
monitor. Pass the returned monitor ID as `monitorId`. Use
[List Webhooks](/api-reference/webhooks/list) to inspect receivers. Use
[List Deliveries](/api-reference/webhooks/deliveries) to audit each delivery.
This route lists monitor settings, not stored events.

## What does the monitor inventory include?

Each row shows the monitor ID, username, and stable X user ID for account joins.
The `eventTypes` array lists the tweet and profile changes the monitor tracks.
The `isActive` field separates running monitors from paused ones.
The timestamps show when Xquik created the monitor and its next billing point.

Tweet filters cover new posts, replies, quotes, reposts, media, and links. They
also cover polls, mentions, hashtags, and long-form posts. Profile filters
include the avatar, banner, name, username, biography, and location. They also
cover URL, verification, protection, pinned tweets, and account availability.
Read `eventTypes` from every row. Do not assume every monitor uses identical
filters.

The response also includes `total`. Compare it with the emitted monitor count.
A mismatch usually means the client dropped rows during local processing. The
route returns up to 200 monitors per page. When `hasMore` is `true`, pass
`nextCursor` as `cursor` to read the next page.

## Does this route return tweets or analytics?

No. `GET /monitors` returns account-monitor configurations. It does not return
tweet timelines, engagement totals, audience reports, or sentiment scores.
Use [List Events](/api-reference/events/list) for stored tweet and profile
events. Use [Get Event](/api-reference/events/get) to inspect one stored event.

The route also does not publish or schedule posts. Use the
[X Write API](/api-reference/x-write/create-tweet) for publishing workflows.
Do not use the monitor list as an event feed or a publishing queue.

## How do you set alerts for several X accounts?

First, create one monitor per username. Give each monitor only the event types
its receiver understands. Then create a webhook for the matching event types.
Store the monitor ID with every workflow rule. You can then tell the source when
several profiles send similar events.

Re-list monitors after every create, update, pause, or delete operation. Check
that the intended row exists and has the expected `eventTypes`. Confirm
`isActive` before waiting for a new alert. Paused monitors retain their
settings. They stop polling until reactivated.

Audit webhook deliveries separately. Join a delivery to its stored event with
the documented event ID. Do not infer success from the monitor's active state.
Polling state and webhook delivery status are separate.

## How should teams manage many tracked profiles?

Assign one owner when managing multiple Twitter accounts. Store that owner
outside the API response. Save the monitor ID, X user ID, selected event types,
and active state. Add the owner and review date.

Assign ownership by workflow. Support teams can process replies and mentions.
Research teams can own new posts, quotes, or media events. Account teams can
own profile-name, biography, verification, or availability changes. Match each
assignment to the exact `eventTypes` returned for that monitor.

Agencies should separate client profiles before reporting active-monitor
costs. Review paused and active rows together, but count their costs
separately. Record every approved state change. With that history, a cleanup for one
client cannot change another client's monitor.

## Is listing Twitter account monitors free?

Yes. This `GET` request consumes no credits. Active monitors cost 21 credits
per monitor-hour. Paused monitors stay listed and stop active-monitor billing.
Review `isActive` and `nextBillingAt` before enabling more profiles.

A quiet event window is no reason to cut cost. A valid monitor may receive
no matching event during that period. Confirm its owner and selected filters
before pausing it. Delete a monitor only when its configuration is no longer
required.

<CodeGroup>
  ```bash cURL theme={null}
  curl -X GET https://xquik.com/api/v1/monitors \
    -H "x-api-key: xq_YOUR_KEY_HERE" | jq -c '.monitors[] | {
      monitor_id: .id,
      username,
      x_user_id: .xUserId,
      event_types: .eventTypes,
      is_active: .isActive,
      created_at: .createdAt,
      next_billing_at: .nextBillingAt,
      monitor_detail_endpoint: ("/api/v1/monitors/" + .id),
      events_endpoint: ("/api/v1/events?monitorId=" + .id),
      event_detail_endpoint_pattern: "/api/v1/events/{event_id}",
      webhooks_endpoint: "/api/v1/webhooks",
      deliveries_endpoint_pattern: "/api/v1/webhooks/{webhook_id}/deliveries"
    }'
  ```

  ```javascript Node.js theme={null}
  const response = await fetch("https://xquik.com/api/v1/monitors", {
    method: "GET",
    headers: {
      "x-api-key": "xq_YOUR_KEY_HERE",
    },
  });
  const payload = await response.json();
  for (const monitor of payload.monitors) {
    const monitorRow = {
      monitor_id: monitor.id,
      username: monitor.username,
      x_user_id: monitor.xUserId,
      event_types: monitor.eventTypes,
      is_active: monitor.isActive,
      created_at: monitor.createdAt,
      next_billing_at: monitor.nextBillingAt,
      monitor_detail_endpoint: `/api/v1/monitors/${monitor.id}`,
      events_endpoint: `/api/v1/events?monitorId=${monitor.id}`,
      event_detail_endpoint_pattern: "/api/v1/events/{event_id}",
      webhooks_endpoint: "/api/v1/webhooks",
      deliveries_endpoint_pattern: "/api/v1/webhooks/{webhook_id}/deliveries",
    };
    process.stdout.write(`${JSON.stringify(monitorRow)}\n`);
  }
  ```

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

  response = requests.get(
      "https://xquik.com/api/v1/monitors",
      headers={"x-api-key": "xq_YOUR_KEY_HERE"},
  )
  payload = response.json()
  for monitor in payload["monitors"]:
      monitor_row = {
          "monitor_id": monitor["id"],
          "username": monitor["username"],
          "x_user_id": monitor["xUserId"],
          "event_types": monitor["eventTypes"],
          "is_active": monitor["isActive"],
          "created_at": monitor["createdAt"],
          "next_billing_at": monitor["nextBillingAt"],
          "monitor_detail_endpoint": f"/api/v1/monitors/{monitor['id']}",
          "events_endpoint": f"/api/v1/events?monitorId={monitor['id']}",
          "event_detail_endpoint_pattern": "/api/v1/events/{event_id}",
          "webhooks_endpoint": "/api/v1/webhooks",
          "deliveries_endpoint_pattern": "/api/v1/webhooks/{webhook_id}/deliveries",
      }
      print(json.dumps(monitor_row))
  ```

  ```go Go theme={null}
  package main

  import (
      "encoding/json"
      "log"
      "net/http"
      "os"
  )

  type Monitor struct {
      ID            string   `json:"id"`
      Username      string   `json:"username"`
      XUserID       string   `json:"xUserId"`
      EventTypes    []string `json:"eventTypes"`
      IsActive      bool     `json:"isActive"`
      CreatedAt     string   `json:"createdAt"`
      NextBillingAt string   `json:"nextBillingAt"`
  }

  type MonitorListResponse struct {
      Monitors []Monitor `json:"monitors"`
      Total    int       `json:"total"`
  }

  type MonitorRow struct {
      DeliveriesEndpointPattern  string   `json:"deliveries_endpoint_pattern"`
      EventDetailEndpointPattern string   `json:"event_detail_endpoint_pattern"`
      EventsEndpoint             string   `json:"events_endpoint"`
      EventTypes                 []string `json:"event_types"`
      CreatedAt                  string   `json:"created_at"`
      IsActive                   bool     `json:"is_active"`
      MonitorDetailEndpoint      string   `json:"monitor_detail_endpoint"`
      MonitorID                  string   `json:"monitor_id"`
      NextBillingAt              string   `json:"next_billing_at"`
      Username                   string   `json:"username"`
      WebhooksEndpoint           string   `json:"webhooks_endpoint"`
      XUserID                    string   `json:"x_user_id"`
  }

  func main() {
      req, err := http.NewRequest("GET", "https://xquik.com/api/v1/monitors", nil)
      if err != nil {
          log.Fatal(err)
      }
      req.Header.Set("x-api-key", "xq_YOUR_KEY_HERE")

      resp, err := http.DefaultClient.Do(req)
      if err != nil {
          log.Fatal(err)
      }
      defer resp.Body.Close()

      var payload MonitorListResponse
      if err := json.NewDecoder(resp.Body).Decode(&payload); err != nil {
          log.Fatal(err)
      }
      encoder := json.NewEncoder(os.Stdout)
      for _, monitor := range payload.Monitors {
          row := MonitorRow{
              DeliveriesEndpointPattern:  "/api/v1/webhooks/{webhook_id}/deliveries",
              EventDetailEndpointPattern: "/api/v1/events/{event_id}",
              EventsEndpoint:             "/api/v1/events?monitorId=" + monitor.ID,
              EventTypes:                 monitor.EventTypes,
              CreatedAt:                  monitor.CreatedAt,
              IsActive:                   monitor.IsActive,
              MonitorDetailEndpoint:      "/api/v1/monitors/" + monitor.ID,
              MonitorID:                  monitor.ID,
              NextBillingAt:              monitor.NextBillingAt,
              Username:                   monitor.Username,
              WebhooksEndpoint:           "/api/v1/webhooks",
              XUserID:                    monitor.XUserID,
          }
          if err := encoder.Encode(row); err != nil {
              log.Fatal(err)
          }
      }
  }
  ```
</CodeGroup>

The Node.js, Python, and Go examples emit one structured monitor record.
Save each record with its support, event, and webhook audit history.

## Inventory handoff

Use `GET /monitors` after create, update, pause, or delete operations to rebuild
your account monitor inventory. The response returns up to 200 monitors ordered
by creation time and a `total` count for the returned set.

| Account monitor inventory column | Response source | Inventory check |
| - | - | - |
| Monitor ID | `monitors[].id` | Use this ID for status, updates, and events. |
| X username | `monitors[].username` | Display the tracked account without `@`. |
| X user ID | `monitors[].xUserId` | Use this stable ID for account joins. |
| Event filter | `monitors[].eventTypes` | Compare these types with webhook subscriptions. |
| Polling state | `monitors[].isActive` | Separate active and paused account monitors. |
| Billing checkpoint | `monitors[].nextBillingAt` | Schedule the next active monitor credit check. |
| Inventory count | `total` | Compare this count with emitted monitor rows. |

<CardGroup cols={2}>
  <Card title="Tracked accounts" icon="users">
    Store each monitor's `id`, `username`, and `xUserId` with your CRM,
    warehouse, or queue records.
  </Card>

  <Card title="Detail handoff" icon="file-search">
    Use [Get Monitor](/api-reference/monitors/twitter-account-monitor-status) with each `id` when a
    support workflow needs the latest event filter, active state, or billing
    checkpoint for one account monitor.
  </Card>

  <Card title="Active billing" icon="activity">
    Filter monitors where `isActive` is `true`. Each active account monitor
    bills 21 credits per active monitor-hour. Use `nextBillingAt` to schedule
    credit checks or pause stale alerts.
  </Card>

  <Card title="Webhook alignment" icon="webhook">
    Compare each monitor's `eventTypes` with [List Webhooks](/api-reference/webhooks/list)
    before relying on signed alerts.
  </Card>

  <Card title="Event backfill" icon="database">
    Use `id` as `monitorId` with [List Events](/api-reference/events/list) to
    audit stored account monitor events. Open one returned ID with
    [Get Event](/api-reference/events/get) to inspect the complete stored event.
  </Card>

  <Card title="Delivery audit" icon="link">
    Use [List Deliveries](/api-reference/webhooks/deliveries) for each webhook
    and join delivery `streamEventId` to event IDs. Do not use `x_event_id` as
    the delivery join key.
  </Card>

  <Card title="State repair" icon="sliders-horizontal">
    Use [Update Monitor](/api-reference/monitors/update) to replace `eventTypes`
    or toggle `isActive`. Use [Delete Monitor](/api-reference/monitors/delete-twitter-account-monitor)
    only when the tracked account should stop permanently.
  </Card>
</CardGroup>

## Reconcile an account monitor inventory

Store one row per monitor ID. Include its username, X user ID, and event types. Add the active state and billing date.

Join monitors to webhooks by configured ownership. Flag missing webhooks, extra webhooks, and mismatched event types.

Compare completed snapshots to identify new, paused, resumed, or removed monitors. Do not compare incomplete snapshots.

Use the single-monitor route for an incident review. Update only the monitors approved for change.

## Assign account monitor ownership

Use the complete list to assign every tracked X profile. Start with monitor ID,
`username`, and stable `xUserId`. Keep the stable ID when a username changes.

Group rows by the team consuming their events. Support teams may own reply and
mention events. Research teams may own new posts. Account operations may own
profile changes. Store ownership outside returned API fields.

Compare `eventTypes` with the events each receiver handles. A webhook receiving only
tweet events cannot process a profile biography change. Flag missing
subscriptions before calling the monitor healthy.

Then inspect active state. Active monitors can produce new account events.
Paused monitors keep their configuration and do not poll. Keep both groups in
the inventory. Never treat a paused row as deleted.

Use `nextBillingAt` for active-budget reviews. Listing remains free. Count
active account monitors separately from keyword monitors. They track different targets and
event types.

Publish one ownership row per monitor ID. Include username, X user ID, event
types, active state, and billing checkpoint. Add its owner and review date.
Later monitor changes then show up as changed rows.

## Prepare a bulk account monitor cleanup

Begin from one complete list response. Do not combine partial snapshots. Mark
rows lacking an owner, current workflow, or required webhook subscription.

Inspect recent stored events before proposing a pause. An empty window does not
prove the profile is irrelevant. Confirm the account, event types, and review
window with the owner.

Pause monitors through the update route first. Keep their IDs and previous
event types in the change record. Watch receiver queues before you
delete.

Delete only approved rows. Re-list monitors after every batch. Confirm removed
IDs are absent and paused IDs remain present. Record billing checkpoints for
the remaining active rows.

Handle uncertain changes individually. Use the single-monitor status route for
each affected ID. Never replay a bulk delete because the client lost its local
response.

## Headers

<ParamField header="x-api-key" type="string" required>
  Your API key. You can also sign in with a session cookie. Create a key from the [dashboard](https://xquik.com/dashboard).
</ParamField>

## Query parameters

<ParamField query="limit" type="integer">
  Maximum items per page: 1 to 200, default 200.
</ParamField>

<ParamField query="cursor" type="string">
  `nextCursor` from the previous page. The `after` alias also works. Offset pagination is not
  supported.
</ParamField>

## Response

### 200 OK

<ResponseField name="monitors" type="object[]">
  Array of monitor objects.
</ResponseField>

<ResponseField name="monitors[].id" type="string">
  Unique monitor ID.
</ResponseField>

<ResponseField name="monitors[].username" type="string">
  Normalized X username.
</ResponseField>

<ResponseField name="monitors[].xUserId" type="string">
  Resolved X user ID.
</ResponseField>

<ResponseField name="monitors[].eventTypes" type="string[]">
  Subscribed event types.
</ResponseField>

<ResponseField name="monitors[].isActive" type="boolean">
  Whether the monitor is active.
</ResponseField>

<ResponseField name="monitors[].createdAt" type="string">
  ISO 8601 creation timestamp.
</ResponseField>

<ResponseField name="monitors[].nextBillingAt" type="string">
  Next hourly credit charge time for active monitor billing.
</ResponseField>

<ResponseField name="total" type="number">
  Account monitors on this page.
</ResponseField>

<ResponseField name="hasMore" type="boolean">
  Whether more rows follow this page.
</ResponseField>

<ResponseField name="nextCursor" type="string">
  Pass it as `cursor` for the next page. Present when `hasMore` is `true`.
</ResponseField>

```json theme={null}
{
  "monitors": [
    {
      "id": "7",
      "username": "elonmusk",
      "xUserId": "44196397",
      "eventTypes": ["tweet.new", "tweet.reply"],
      "isActive": true,
      "createdAt": "2026-02-24T10:30:00.000Z",
      "nextBillingAt": "2026-02-24T11:30:00.000Z"
    },
    {
      "id": "12",
      "username": "xquik_",
      "xUserId": "1849726401547751424",
      "eventTypes": ["tweet.new", "tweet.quote", "tweet.reply", "tweet.retweet"],
      "isActive": true,
      "createdAt": "2026-02-25T14:00:00.000Z",
      "nextBillingAt": "2026-02-25T15:00:00.000Z"
    }
  ],
  "total": 2,
  "hasMore": false
}
```

### 400 Invalid cursor

```json theme={null}
{
  "error": "invalid_input",
  "message": "Cursor invalid. Use nextCursor from the previous page, or omit it to start over."
}
```

The `cursor` is not one this list returned. Send the `nextCursor` of the previous page, or omit it.

### 401 Missing API key

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

Missing or invalid API key.

### 429 Rate limited

```json theme={null}
{
  "error": "rate_limit_exceeded",
  "message": "Too many requests. Try again later.",
  "retryAfter": 1
}
```

Too many requests. Wait for the `Retry-After` header before retrying.

<Info>
  Returns up to 200 monitors per page. Pass `nextCursor` as `cursor` for the next page.
</Info>

<Note>
  **Related.** [Create Monitor](/api-reference/monitors/create) to add a new monitor, [Get Monitor](/api-reference/monitors/twitter-account-monitor-status) to fetch one monitor, [List Events](/api-reference/events/list) to audit stored events, [Get Event](/api-reference/events/get) to inspect one event, [List Webhooks](/api-reference/webhooks/list) to compare subscriptions, or [List Deliveries](/api-reference/webhooks/deliveries) to audit webhook delivery status.
</Note>


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