# X (Twitter) Keyword Monitor – Track Mentions, Hashtags (`b2b_leads/x-keyword-mention-monitor`) Actor

Monitor X (Twitter) for keywords, hashtags, cashtags & @mentions in real time. Scrape the latest matching tweets or run scheduled checks that return only new posts since the last run. Filter by language, likes & retweets, push results to a webhook, and export JSON/CSV/Excel.

- **URL**: https://apify.com/b2b\_leads/x-keyword-mention-monitor.md
- **Developed by:** [Chidubem Aneke](https://apify.com/b2b_leads) (community)
- **Categories:** Social media, Lead generation, MCP servers
- **Stats:** 1 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.15 / 1,000 results

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

Learn more: https://docs.apify.com/platform/actors/running/actors-in-store#pay-per-event

## What's an Apify Actor?

Actors are a software tools running on the Apify platform, for all kinds of web data extraction and automation use cases.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.
Actors are written with capital "A".

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.
The best way to integrate Actors is as follows.

In JavaScript/TypeScript projects, use official [JavaScript/TypeScript client](https://docs.apify.com/api/client/js.md):

```bash
npm install apify-client
```

In Python projects, use official [Python client library](https://docs.apify.com/api/client/python.md):

```bash
pip install apify-client
```

In shell scripts, use [Apify CLI](https://docs.apify.com/cli/docs.md):

````bash
# MacOS / Linux
curl -fsSL https://apify.com/install-cli.sh | bash
# Windows
irm https://apify.com/install-cli.ps1 | iex
```bash

In AI frameworks, you might use the [Apify MCP server](https://docs.apify.com/platform/integrations/mcp.md).

If your project is in a different language, use the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).


# README

## X (Twitter) Keyword Monitor — Real-Time Alerts for New Tweets

**Watch X (Twitter) for the terms that matter.** Track keywords, hashtags, cashtags, and @mentions — fetch the **latest tweets** in one shot, or run on a **schedule** and get only what's new since the last run.

No X API keys. No developer account. No browser automation to babysit. Pick a run mode, type your terms, and press **Start**.

> ⚡ **Two run modes** — latest snapshot or incremental monitor • 🔔 **Optional webhook** • 🗓️ **Schedule-ready** • 🤖 **LLM & MCP-ready** JSON

---

### Why this Actor

- **Two run modes.** **Latest tweets** (default) — grab the N most recent posts for your keyword right now, no saved history. **New since last run** — for schedules; returns only tweets posted since the previous run, with no duplicates.
- **Keywords, hashtags, cashtags, mentions.** Watch `product launch`, `#AI`, `$TSLA`, or `@yourbrand` — mix and match. Plain terms are auto-combined into efficient OR queries; power users can pass full X search queries with operators.
- **Instant delivery, safely.** Point it at a webhook and new tweets are POSTed to your endpoint as they're found. Every tweet is saved to the dataset **first**, so a webhook hiccup never loses data.
- **Never loses a run to one bad query.** A query that errors becomes a tidy `unavailable` row — the rest of your monitor keeps going.
- **Ultra-light & cheap.** Pure HTTP, streams results as they arrive, runs comfortably on **256 MB**.

---

### Use cases & outcomes

**🔔 Brand & mention monitoring**
Get alerted the moment someone mentions your brand, product, or executives. Route new tweets straight to Slack, a webhook, a database, or an AI agent.

**👂 Social listening**
Track topics, campaigns, and conversations as they happen. Filter by language and minimum likes to focus on signal, not noise.

**🏁 Competitor & campaign tracking**
Watch competitor names, product hashtags, or event tags and see new activity on every run — build a timeline of what's being said and when.

**📈 Cashtag & market chatter**
Monitor `$TSLA`, `$BTC`, or any cashtag for fresh posts to feed trading signals, dashboards, or research.

**🚨 Real-time alerts & incident detection**
Watch for outage keywords, crisis terms, or security mentions and trigger downstream automations the instant new tweets appear.

**🤖 AI agents & RAG pipelines**
Feed a continuous stream of clean, flat JSON into an LLM. Stable field names and a `query` tag on every row mean no brittle parsing.

---

### How it works

Choose a **Run mode** in the input form:

| Mode | Best for | What it does |
|------|----------|--------------|
| **Latest tweets** (default) | One-off runs, research, "give me 100 recent posts" | Fetches up to `maxNewPerQuery` newest tweets per keyword. **No saved state** — every run is independent. |
| **New since last run** | Apify Schedules (every 15 min, hourly, …) | Remembers the newest tweet ID per query. Each run returns **only tweets newer than that**, then updates the watermark. |

Both modes search **newest-first**. In incremental mode the Actor stops paginating as soon as it hits a tweet from a previous run — so scheduled runs stay fast and cheap.

> **Incremental first run:** no history yet, so it backfills up to `maxNewPerQuery` recent tweets and sets the baseline. From run #2 on, you get only genuinely new posts.

---

### Quick start

1. Open the Actor in Apify Console.
2. Enter your **keywords**, **hashtags/cashtags**, or **mentions**.
3. Leave **Run mode** on **Latest tweets** (default) for a one-shot pull, or switch to **New since last run** before scheduling.
4. Press **Start**.
5. Export as **JSON / CSV / Excel**, pull via the **Apify API**, or receive them at your **webhook**.

#### Try it — latest 100 tweets (default)

```json
{
  "keywords": ["AI agents", "LLM", "#ai"],
  "runMode": "latest",
  "maxNewPerQuery": 100
}
````

#### Scheduled brand monitoring (incremental)

```json
{
  "keywords": ["Acme Corp", "AcmeCloud"],
  "mentions": ["acmecorp"],
  "runMode": "incremental",
  "stateKey": "brand-monitor",
  "webhookUrl": "https://hooks.example.com/x-new-tweets"
}
```

#### Cashtag stream, high-signal only

```json
{
  "keywords": ["$TSLA", "$NVDA"],
  "minLikes": 25,
  "excludeRetweets": true,
  "maxItems": 300
}
```

#### Advanced query (full X operators)

```json
{
  "queries": ["(outage OR downtime) (\"acme\" OR @acmecorp) -is:retweet lang:en"],
  "runMode": "latest",
  "maxNewPerQuery": 50
}
```

***

### Schedule this Actor

For ongoing monitoring, set **Run mode** to **New since last run**, then create an Apify Schedule:

1. Go to **Schedules → Create schedule**.
2. Add this Actor (or a saved Task with your input).
3. Set a cron expression — e.g. `*/15 * * * *` (every 15 minutes), `0 * * * *` (hourly).
4. Save. Each run continues from where the last one left off.

**Running several monitors?** Give each schedule a different **Monitor ID** (`stateKey` in the API), e.g. `brand-monitor` and `competitor-monitor`.

***

### Input reference

| Field | Type | Default | Description |
|-------|------|---------|-------------|
| `keywords` | string\[] | `[]` | Plain terms, auto-combined into OR queries. Terms starting with `#` become hashtags, `$` become cashtags. |
| `queries` | string\[] | `[]` | Full X search query strings, passed through verbatim (supports `min_faves:`, `lang:`, `-is:retweet`, `from:`, `to:`, etc.). |
| `mentions` | string\[] | `[]` | Handles to monitor for mentions (with or without `@`). |
| `runMode` | select | `latest` | `latest` = fetch N most recent tweets (one-shot). `incremental` = only tweets since last run (for schedules). |
| `stateKey` | string | `default` | **Incremental mode only** (shown as **Monitor ID** in Console). Unique name for saved history. Ignored in `latest` mode. |
| `language` | string | `""` | Optional ISO language code filter (e.g. `en`). |
| `minLikes` | integer | `0` | Keep only tweets with at least this many likes. `0` = off. |
| `excludeRetweets` | boolean | `false` | Exclude retweets. |
| `maxNewPerQuery` | integer | `100` | Max tweets per query. In `latest` mode = how many recent posts to fetch. In `incremental` mode = cap per run (`0` = unlimited within `maxItems`). |
| `maxItems` | integer | `0` | Global ceiling per run across all queries. `0` = unlimited (up to 100,000). Use `maxNewPerQuery` to cap each keyword. |
| `webhookUrl` | string | `""` | Optional http(s) endpoint; tweets POSTed in per-query batches. |
| `webhookBatchSize` | integer | `100` | Max tweets per webhook POST. |
| `includeRaw` | boolean | `false` | Attach the untouched upstream payload under `raw` on each record. |
| `maxRetries` | integer | `5` | Retries on rate limits / server errors. |
| `retryBaseDelayMs` | integer | `2000` | Base backoff delay (grows exponentially). |
| `retryMaxDelayMs` | integer | `30000` | Maximum backoff delay. |

You must provide at least one of `keywords`, `queries`, or `mentions`.

***

### Output

Each tweet is a **rich JSON object** tagged with the `query` that matched it:

```json
{
  "featureType": "monitor",
  "query": "(\"AI agents\" OR #ai)",
  "scrapedAt": "2026-07-06T12:15:00.000Z",
  "id": "1900000000000000003",
  "url": "https://x.com/nasa/status/1900000000000000003",
  "text": "Exploring the universe with AI agents…",
  "lang": "en",
  "createdAt": "2026-07-06T12:14:00.000Z",
  "source": "Twitter Web App",
  "type": "tweet",
  "likeCount": 1240,
  "replyCount": 42,
  "retweetCount": 320,
  "quoteCount": 15,
  "bookmarkCount": 8,
  "viewCount": 98000,
  "engagementTotal": 1625,
  "engagementRate": 0.0166,
  "hashtags": ["ai"],
  "symbols": ["TSLA"],
  "mentions": [{ "username": "openai", "id": "...", "name": "OpenAI" }],
  "urls": [{ "url": "https://…", "expandedUrl": "https://…", "displayUrl": "…" }],
  "media": [{ "type": "video", "url": "https://…mp4", "previewUrl": "https://…jpg", "durationMs": 24334, "variants": [{ "bitrate": 2176000, "contentType": "video/mp4", "url": "https://…720x960.mp4" }] }],
  "poll": null,
  "card": { "title": "…", "description": "…", "domain": "youtube.com", "imageUrl": "https://…", "appName": "YouTube" },
  "place": { "name": "Baltimore", "country": "United States", "countryCode": "US" },
  "community": null,
  "hasMedia": true, "mediaTypes": ["video"], "hasLinks": true, "hasPoll": false, "hasCard": true,
  "isReply": false, "isRetweet": false, "isQuote": false, "isEdited": false,
  "possiblySensitive": false, "isPromoted": false, "isPaidPromotion": false,
  "hasAIGeneratedMedia": false, "hasBirdwatchNotes": false,
  "quotedTweet": null,
  "retweetedTweet": null,
  "authorUsername": "nasa",
  "author": {
    "id": "...", "username": "nasa", "displayName": "NASA", "bio": "…",
    "followersCount": 90000000, "followingCount": 200, "tweetCount": 70000,
    "favoritesCount": 1200, "verified": true, "isBlueVerified": true,
    "professionalType": "Business", "professionalCategories": ["Science"],
    "location": "…", "website": "https://nasa.gov", "createdAt": "…", "accountAgeDays": 6200
  }
}
```

**What each tweet captures**

| Group | Fields |
|-------|--------|
| Core | `id`, `url`, `text`, `lang`, `createdAt`, `source` (posting client), `type`, `conversationId` |
| Engagement | `likeCount`, `replyCount`, `retweetCount`, `quoteCount`, `bookmarkCount`, `viewCount`, plus derived `engagementTotal` and `engagementRate` |
| Entities | `hashtags`, `symbols` (cashtags), `mentions`, `urls`, and convenience flags `hasMedia`, `mediaTypes`, `hasLinks`, `hasPoll`, `hasCard` |
| Media | `media[]` with photos, GIFs, and **playable video renditions** (`variants[]` bitrate/URL), plus `durationMs`, `altText`, `aspectRatio`, `sensitiveMedia` |
| Rich objects | `poll` (options + votes), `card` (link preview: title/description/domain/image/app), `place` (geo), `community` |
| Context | `replyTo`, `quotedTweetId`/`quotedTweet` (full embedded tweet), `retweetedTweetId`/`retweetedTweet` (full embedded tweet) |
| Signals | `isReply`, `isRetweet`, `isQuote`, `isEdited`, `possiblySensitive`, `isPromoted`, `isPaidPromotion`, `hasAIGeneratedMedia`, `hasBirdwatchNotes` (Community Notes) |
| Author | full profile incl. `favoritesCount`, `professionalType`/`professionalCategories`, verification fields, `pinnedTweetIds`, and derived `accountAgeDays` |

A query that can't be fetched produces an explicit marker instead of a silent gap:

```json
{
  "featureType": "unavailable",
  "inputRef": "(\"AI agents\" OR #ai)",
  "status": "unavailable",
  "reason": "rate_limited",
  "message": "…",
  "scrapedAt": "2026-07-06T12:15:00.000Z"
}
```

#### Dataset views

The dataset ships with ready-made tabbed views in the Console — sorted **newest first**:

| View | What it shows |
|------|----------------|
| **Overview** | All records: tweets (`featureType: monitor`) plus any failed queries (`unavailable`), with engagement totals. |
| **New tweets** | Engagement columns, language, client, hashtags, cashtags, and media/link flags. |
| **Top engagement** | Tweets ranked by total engagement and engagement rate. |
| **Authors** | Flattened author profiles (followers, verification, professional type, account age, bio). |
| **Verified & pro authors** | Author details focused on verification and business/creator accounts — for lead-gen and credibility filtering. |
| **Media** | Media-bearing tweets with type breakdown and the full media array (incl. video renditions). |
| **Links & cards** | Tweets with outbound links or link-preview cards (title/description/domain) — brand/PR monitoring. |
| **Polls** | Tweets with polls, options, and vote tallies. |
| **Geo** | Tweets with an attached place (city/country) for location trends. |
| **Community Notes** | Tweets flagged with a Community Note — misinformation tracking. |
| **Promoted** | Promoted / paid-promotion tweets — ad intelligence. |
| **Unavailable** | Queries that errored this run (the monitor keeps going). |

Every field is also documented in the dataset schema for Apify MCP and agent tooling.

#### Run summary (OUTPUT)

After every run, the **OUTPUT** tab shows a summary:

```json
{
  "runMode": "incremental",
  "stateKey": "brand-monitor",
  "totalNew": 12,
  "queryResults": [
    {
      "query": "(\"AI agents\" OR #ai)",
      "firstRun": false,
      "newCount": 12,
      "previousMaxId": "1899999999999999990",
      "newMaxId": "1900000000000000003",
      "newestCreatedAt": "2026-07-06T12:14:00.000Z",
      "webhookDelivered": 12,
      "webhookFailed": 0
    }
  ],
  "upstreamRequestCount": 3,
  "webhookConfigured": true,
  "errors": []
}
```

***

### Webhook payload

When `webhookUrl` is set, the monitor POSTs new tweets in per-query batches (chunked by `webhookBatchSize`):

```json
{
  "type": "x_keyword_monitor.new_tweets",
  "query": "(\"AI agents\" OR #ai)",
  "count": 12,
  "chunkIndex": 0,
  "deliveredAt": "2026-07-06T12:15:00.000Z",
  "runId": "…",
  "actorRunUrl": "https://console.apify.com/view/runs/…",
  "tweets": [ { "...": "canonical tweet object" } ]
}
```

Delivery is best-effort with automatic retry/backoff. **Tweets are always written to the dataset before any webhook attempt**, so a failed webhook never loses data — failures are counted in the run summary.

***

### Built for LLMs, agents & MCP

- **Flat, predictable records** — `camelCase` keys, `null` for missing values, no deep nesting.
- **A `query` tag on every row** — agents know exactly which watch term produced each tweet.
- **Canonical URLs & ISO timestamps** — every tweet has a full `https://x.com/...` link and UTC dates.

Use it through **Apify MCP** or export JSON/CSV from the dataset API and pipe into your pipeline.

***

### FAQ

**Do I need an X/Twitter API key?** No. It works out of the box.

**What's the difference between the two run modes?** **Latest tweets** (default) fetches the N most recent posts and ignores any saved history — use it when you just want "give me 100 tweets for this keyword." **New since last run** is for schedules: each run returns only tweets posted since the previous run.

**Will I get duplicate tweets across runs?** In **incremental** mode, no — the Actor tracks the newest tweet ID per query. In **latest** mode, each run is independent (you may see the same tweets if you run again without changing inputs).

**What happens on the first incremental run?** No history yet, so it backfills up to `maxNewPerQuery` recent tweets and sets the baseline. From run #2 on, you get only new tweets.

**Why did I get zero tweets?** In **incremental** mode, that usually means nothing new was posted since the last run. In **latest** mode, check your keywords/filters — the query may genuinely have no matches.

**How do I run multiple scheduled monitors?** Use **incremental** mode and give each schedule a different **Monitor ID** (`stateKey`).

**What formats can I export?** JSON, CSV, Excel, HTML, or RSS — plus the Apify API, webhooks, and integrations.

***

### Support

Open an issue on the Actor page or contact the publisher with your run ID and your (redacted) input JSON.

***

### Contact me

Need something built beyond this Actor? I take on **custom projects** of all sizes — from one-off scrapers to full products.

| | |
|---|---|
| **Email** | <dubem115@gmail.com> |
| **GitHub** | [github.com/DrunkCodes](https://github.com/DrunkCodes) |

**What I can help with:**

- **Scraping & data extraction** — Apify Actors and scrapers for X, Amazon, LinkedIn, e-commerce, lead gen, and any site or API you need
- **Automation & pipelines** — scheduled monitors, webhooks, enrichment, and export to Sheets, databases, or your stack
- **Web apps** — dashboards, SaaS tools, internal tools, APIs, and full-stack applications of any kind

Send a short description of what you want built and your timeline — happy to discuss scope and pricing.

# Actor input Schema

## `keywords` (type: `array`):

Plain terms to watch, auto-combined into OR queries (e.g. "customer support", "data breach"). Terms starting with # are treated as hashtags and terms starting with $ as cashtags (e.g. #ai, $tsla). Leave empty if you use Queries or Mentions instead.

## `queries` (type: `array`):

Full X search query strings, passed through verbatim. Supports operators such as min\_faves:, lang:, -is:retweet, from:, to:, filter:links, and quoted phrases. Use this for precise control.

## `mentions` (type: `array`):

X handles to monitor for mentions, with or without the leading @ (e.g. openai, @nasa). Each handle is added to the watched queries as @handle.

## `runMode` (type: `string`):

How this run should behave. "Latest tweets" fetches the most recent posts matching your keywords (default — good for one-off runs). "New since last run" is for scheduled monitoring: only tweets posted since the previous run are returned, using saved state.

## `stateKey` (type: `string`):

A unique name for this monitor's saved history. The Actor remembers the newest tweet it has seen under this name, so the next scheduled run continues from there. Use one ID per schedule — e.g. brand-monitor, competitor-monitor. Leave as default if you only have one incremental monitor. Ignored when Run mode is Latest tweets.

## `language` (type: `string`):

Optional ISO language code (e.g. en, es, ja). Applied in the query and re-validated after fetch. Leave empty for all languages.

## `minLikes` (type: `integer`):

Only keep tweets with at least this many likes. Set 0 to disable. Applied both in the query and re-validated after fetch.

## `excludeRetweets` (type: `boolean`):

Exclude retweets from the results.

## `maxNewPerQuery` (type: `integer`):

Maximum tweets to return for each query in one run. In "Latest tweets" mode this is the number of most recent posts to fetch (default 100). In "New since last run" mode this caps how many new tweets are collected per query per run (0 = unlimited within Max items).

## `maxItems` (type: `integer`):

Global ceiling on total tweets returned across all queries in one run. 0 = unlimited (up to 100,000). Use max tweets per query to cap each keyword individually.

## `webhookUrl` (type: `string`):

Optional http(s) endpoint. New tweets are POSTed here in per-query JSON batches as they are found. Delivery is best-effort: tweets are always saved to the dataset first, so a webhook failure never loses data.

## `webhookBatchSize` (type: `integer`):

Maximum tweets per webhook POST. Larger batches mean fewer requests; smaller batches mean smaller payloads.

## `includeRaw` (type: `boolean`):

Attach the untouched upstream payload under a "raw" key on each tweet record (for power users). Increases record size.

## `maxRetries` (type: `integer`):

Automatic retries on rate limits (429) and server errors (5xx) before giving up on a request.

## `retryBaseDelayMs` (type: `integer`):

Base backoff delay between retries; grows exponentially and is capped by the max delay.

## `retryMaxDelayMs` (type: `integer`):

Maximum backoff delay between retries.

## Actor input object example

```json
{
  "keywords": [
    "AI agents"
  ],
  "queries": [],
  "mentions": [],
  "runMode": "latest",
  "stateKey": "default",
  "language": "",
  "minLikes": 0,
  "excludeRetweets": false,
  "maxNewPerQuery": 100,
  "maxItems": 0,
  "webhookUrl": "",
  "webhookBatchSize": 100,
  "includeRaw": false,
  "maxRetries": 5,
  "retryBaseDelayMs": 2000,
  "retryMaxDelayMs": 30000
}
```

# Actor output Schema

## `newTweets` (type: `string`):

All tweets that are new since the previous run, tagged with the query that matched them.

## `overview` (type: `string`):

Key fields for every record (new tweets and any unavailable query markers), newest first.

## `authors` (type: `string`):

Flattened author profiles for each new tweet — useful for influencer and account analysis.

## `runSummary` (type: `string`):

Per-run metadata: since mode, per-query new-tweet counts, watermarks, total new, upstream request count, and non-fatal errors.

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "keywords": [
        "AI agents"
    ],
    "queries": [],
    "mentions": [],
    "stateKey": "default"
};

// Run the Actor and wait for it to finish
const run = await client.actor("b2b_leads/x-keyword-mention-monitor").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "keywords": ["AI agents"],
    "queries": [],
    "mentions": [],
    "stateKey": "default",
}

# Run the Actor and wait for it to finish
run = client.actor("b2b_leads/x-keyword-mention-monitor").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print("💾 Check your data here: https://console.apify.com/storage/datasets/" + run["defaultDatasetId"])
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "keywords": [
    "AI agents"
  ],
  "queries": [],
  "mentions": [],
  "stateKey": "default"
}' |
apify call b2b_leads/x-keyword-mention-monitor --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=b2b_leads/x-keyword-mention-monitor",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

```json
{
    "openapi": "3.0.1",
    "info": {
        "title": "X (Twitter) Keyword Monitor – Track Mentions, Hashtags",
        "description": "Monitor X (Twitter) for keywords, hashtags, cashtags & @mentions in real time. Scrape the latest matching tweets or run scheduled checks that return only new posts since the last run. Filter by language, likes & retweets, push results to a webhook, and export JSON/CSV/Excel.",
        "version": "0.0",
        "x-build-id": "CcbnLDYpILdogPxy1"
    },
    "servers": [
        {
            "url": "https://api.apify.com/v2"
        }
    ],
    "paths": {
        "/acts/b2b_leads~x-keyword-mention-monitor/run-sync-get-dataset-items": {
            "post": {
                "operationId": "run-sync-get-dataset-items-b2b_leads-x-keyword-mention-monitor",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for its completion, and returns Actor's dataset items in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        },
        "/acts/b2b_leads~x-keyword-mention-monitor/runs": {
            "post": {
                "operationId": "runs-sync-b2b_leads-x-keyword-mention-monitor",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor and returns information about the initiated run in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/runsResponseSchema"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/acts/b2b_leads~x-keyword-mention-monitor/run-sync": {
            "post": {
                "operationId": "run-sync-b2b_leads-x-keyword-mention-monitor",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for completion, and returns the OUTPUT from Key-value store in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        }
    },
    "components": {
        "schemas": {
            "inputSchema": {
                "type": "object",
                "properties": {
                    "keywords": {
                        "title": "Keywords",
                        "type": "array",
                        "description": "Plain terms to watch, auto-combined into OR queries (e.g. \"customer support\", \"data breach\"). Terms starting with # are treated as hashtags and terms starting with $ as cashtags (e.g. #ai, $tsla). Leave empty if you use Queries or Mentions instead.",
                        "default": [],
                        "items": {
                            "type": "string"
                        }
                    },
                    "queries": {
                        "title": "Advanced queries",
                        "type": "array",
                        "description": "Full X search query strings, passed through verbatim. Supports operators such as min_faves:, lang:, -is:retweet, from:, to:, filter:links, and quoted phrases. Use this for precise control.",
                        "default": [],
                        "items": {
                            "type": "string"
                        }
                    },
                    "mentions": {
                        "title": "Mentions",
                        "type": "array",
                        "description": "X handles to monitor for mentions, with or without the leading @ (e.g. openai, @nasa). Each handle is added to the watched queries as @handle.",
                        "default": [],
                        "items": {
                            "type": "string"
                        }
                    },
                    "runMode": {
                        "title": "Run mode",
                        "enum": [
                            "latest",
                            "incremental"
                        ],
                        "type": "string",
                        "description": "How this run should behave. \"Latest tweets\" fetches the most recent posts matching your keywords (default — good for one-off runs). \"New since last run\" is for scheduled monitoring: only tweets posted since the previous run are returned, using saved state.",
                        "default": "latest"
                    },
                    "stateKey": {
                        "title": "Monitor ID",
                        "type": "string",
                        "description": "A unique name for this monitor's saved history. The Actor remembers the newest tweet it has seen under this name, so the next scheduled run continues from there. Use one ID per schedule — e.g. brand-monitor, competitor-monitor. Leave as default if you only have one incremental monitor. Ignored when Run mode is Latest tweets.",
                        "default": "default"
                    },
                    "language": {
                        "title": "Language filter",
                        "type": "string",
                        "description": "Optional ISO language code (e.g. en, es, ja). Applied in the query and re-validated after fetch. Leave empty for all languages.",
                        "default": ""
                    },
                    "minLikes": {
                        "title": "Minimum likes",
                        "minimum": 0,
                        "type": "integer",
                        "description": "Only keep tweets with at least this many likes. Set 0 to disable. Applied both in the query and re-validated after fetch.",
                        "default": 0
                    },
                    "excludeRetweets": {
                        "title": "Exclude retweets",
                        "type": "boolean",
                        "description": "Exclude retweets from the results.",
                        "default": false
                    },
                    "maxNewPerQuery": {
                        "title": "Max tweets per query",
                        "minimum": 0,
                        "type": "integer",
                        "description": "Maximum tweets to return for each query in one run. In \"Latest tweets\" mode this is the number of most recent posts to fetch (default 100). In \"New since last run\" mode this caps how many new tweets are collected per query per run (0 = unlimited within Max items).",
                        "default": 100
                    },
                    "maxItems": {
                        "title": "Max items per run",
                        "minimum": 0,
                        "type": "integer",
                        "description": "Global ceiling on total tweets returned across all queries in one run. 0 = unlimited (up to 100,000). Use max tweets per query to cap each keyword individually.",
                        "default": 0
                    },
                    "webhookUrl": {
                        "title": "Webhook URL",
                        "type": "string",
                        "description": "Optional http(s) endpoint. New tweets are POSTed here in per-query JSON batches as they are found. Delivery is best-effort: tweets are always saved to the dataset first, so a webhook failure never loses data.",
                        "default": ""
                    },
                    "webhookBatchSize": {
                        "title": "Webhook batch size",
                        "minimum": 1,
                        "type": "integer",
                        "description": "Maximum tweets per webhook POST. Larger batches mean fewer requests; smaller batches mean smaller payloads.",
                        "default": 100
                    },
                    "includeRaw": {
                        "title": "Include raw payload",
                        "type": "boolean",
                        "description": "Attach the untouched upstream payload under a \"raw\" key on each tweet record (for power users). Increases record size.",
                        "default": false
                    },
                    "maxRetries": {
                        "title": "Max retries",
                        "minimum": 0,
                        "type": "integer",
                        "description": "Automatic retries on rate limits (429) and server errors (5xx) before giving up on a request.",
                        "default": 5
                    },
                    "retryBaseDelayMs": {
                        "title": "Retry base delay (ms)",
                        "minimum": 0,
                        "type": "integer",
                        "description": "Base backoff delay between retries; grows exponentially and is capped by the max delay.",
                        "default": 2000
                    },
                    "retryMaxDelayMs": {
                        "title": "Retry max delay (ms)",
                        "minimum": 0,
                        "type": "integer",
                        "description": "Maximum backoff delay between retries.",
                        "default": 30000
                    }
                }
            },
            "runsResponseSchema": {
                "type": "object",
                "properties": {
                    "data": {
                        "type": "object",
                        "properties": {
                            "id": {
                                "type": "string"
                            },
                            "actId": {
                                "type": "string"
                            },
                            "userId": {
                                "type": "string"
                            },
                            "startedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "finishedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "status": {
                                "type": "string",
                                "example": "READY"
                            },
                            "meta": {
                                "type": "object",
                                "properties": {
                                    "origin": {
                                        "type": "string",
                                        "example": "API"
                                    },
                                    "userAgent": {
                                        "type": "string"
                                    }
                                }
                            },
                            "stats": {
                                "type": "object",
                                "properties": {
                                    "inputBodyLen": {
                                        "type": "integer",
                                        "example": 2000
                                    },
                                    "rebootCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "restartCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "resurrectCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "computeUnits": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "options": {
                                "type": "object",
                                "properties": {
                                    "build": {
                                        "type": "string",
                                        "example": "latest"
                                    },
                                    "timeoutSecs": {
                                        "type": "integer",
                                        "example": 300
                                    },
                                    "memoryMbytes": {
                                        "type": "integer",
                                        "example": 1024
                                    },
                                    "diskMbytes": {
                                        "type": "integer",
                                        "example": 2048
                                    }
                                }
                            },
                            "buildId": {
                                "type": "string"
                            },
                            "defaultKeyValueStoreId": {
                                "type": "string"
                            },
                            "defaultDatasetId": {
                                "type": "string"
                            },
                            "defaultRequestQueueId": {
                                "type": "string"
                            },
                            "buildNumber": {
                                "type": "string",
                                "example": "1.0.0"
                            },
                            "containerUrl": {
                                "type": "string"
                            },
                            "usage": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "integer",
                                        "example": 1
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "usageTotalUsd": {
                                "type": "number",
                                "example": 0.00005
                            },
                            "usageUsd": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "number",
                                        "example": 0.00005
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
```
