# Xpoz Documentation — Full Text > Social media intelligence platform. Access billions of posts and users across Twitter/X, Instagram, Reddit, and TikTok via MCP, SDKs, CLI, and Agent Skills. This file contains the full text of all Xpoz documentation pages. For a page index, see: https://docs.xpoz.ai/llms.txt For the agent setup guide, see: https://docs.xpoz.ai/agents.md --- # Welcome to Xpoz Source: https://docs.xpoz.ai/introduction **For AI agents:** Start with [agents.md](https://docs.xpoz.ai/agents.md) for the setup and tool-choice guide, or [llms.txt](https://docs.xpoz.ai/llms.txt) for the full documentation index. ## What is Xpoz? Xpoz is a social media intelligence platform that gives you structured access to **billions of posts and users** across Twitter/X, Instagram, Reddit, and TikTok. Search users, posts, comments, and communities using natural language or structured queries. ## How to access Xpoz Choose the integration that fits your workflow: Connect directly from Claude Code, Claude Desktop, Gemini CLI, Cursor, or any MCP-compatible client. Typed async client for Node.js applications. Install via `npm install @xpoz/xpoz`. Sync and async clients for Python. Install via `pip install xpoz`. Command-line interface for quick lookups and scripting. Install via Homebrew, pip, or binary. ## Platform coverage | Platform | Users | Posts | Comments | Communities | |----------|-------|-------|----------|-------------| | **Twitter/X** | Profiles, followers, connections | Search, timelines, retweets, quotes | Replies | - | | **Instagram** | Profiles, followers, connections | Search, user posts, by ID | Post comments | - | | **Reddit** | Profiles, search | Search, by ID with comments | Search comments | Subreddits | | **TikTok** | Profiles, search | Search, user posts, by hashtag | Post comments | - | ## Key capabilities - **Natural language queries** with boolean operators and phrase matching - **Server-side pagination** for large result sets (100 items per page) - **Three response modes**: fast (immediate), paging (iterate pages), CSV (bulk export to S3) - **Field selection** to retrieve only the data you need - **Real-time + historical data** with rolling 60-day windows - **Tracking** for keywords and users across platforms ## Who uses Xpoz - **AI agents** performing social media research and analysis - **Data teams** collecting large-scale social media datasets - **Developers** building social intelligence features into applications - **Researchers** studying trends, sentiment, and public discourse ## Quick links Get started in 2 minutes Browse all 48 tools Pre-built AI workflows --- # Instant Access Source: https://docs.xpoz.ai/trial Need social media data? You're two HTTP calls away from real results. Generate a free token, then start pulling structured data — profiles, posts, comments, and communities across Twitter/X, Instagram, Reddit, and TikTok. No signup, no credit card, no OAuth, no approval process. ## Why start here This is the fastest way to see what Xpoz returns. You'll have a working API key in under a second — every read tool works immediately across all four platforms: user lookups, post searches, comment threads, and community discovery. Same structured data, same API shape as a full access key. ## Get started Generate a free token, then use it as your API key: ```bash # 1. Generate a free token (valid 5 days) TOKEN=$(curl -s -X POST https://api.xpoz.ai/api/trial/token -H "Content-Type: application/json" -d '{"source":""}' | jq -r .data.accessKey) # 2. Use it like any access key curl -X POST https://mcp.xpoz.ai/mcp \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{"jsonrpc":"2.0","method":"tools/call","params":{"name":"getTwitterUser","arguments":{"identifier":"elonmusk","identifierType":"username"}},"id":1}' ``` ```bash export XPOZ_API_KEY=$(curl -s -X POST https://api.xpoz.ai/api/trial/token -H "Content-Type: application/json" -d '{"source":""}' | jq -r .data.accessKey) xpoz-cli twitter get_user --identifier elonmusk ``` ```bash TOKEN=$(curl -s -X POST https://api.xpoz.ai/api/trial/token -H "Content-Type: application/json" -d '{"source":""}' | jq -r .data.accessKey) claude mcp add xpoz-mcp https://mcp.xpoz.ai/mcp \ -t http \ -H "Authorization: Bearer $TOKEN" ``` The request requires a `source` field describing how you discovered Xpoz (e.g. a skill name, a specific page, `sdk`, `cli`). The token endpoint needs no auth and hands back a key that starts with `TRIAL`: ```json { "success": true, "data": { "accessKey": "TRIAL...", "expiresInSeconds": 432000 }, "message": "Trial access token created." } ``` Drop the `TRIAL...` token in wherever an access key goes — the SDK `apiKey`, the `XPOZ_API_KEY` env var, or a `Bearer` header. ## Zero-change upgrade The response format is identical to a full access key — same fields, same shape, same structure. When you're ready to upgrade, swap the token and keep everything else. Your code doesn't change. ## What you get All read tools work instantly across every platform. The only differences from a full access key are result volume and advanced features: | | Instant access | Full access key | |---|---|---| | Data tools (read) | ✅ All 4 platforms | ✅ All 4 platforms | | Results per call | Up to 5 | Full, paginated | | Pagination | — | ✅ | | CSV export | — | ✅ | | Live crawling | — | ✅ | | Validity | 5 days | Ongoing | ## Ready for full access Need larger result sets, pagination, or CSV export? [Get a free access key](https://xpoz.ai/get-token) — still no credit card. The request and response shapes are unchanged, so there's nothing to rewrite. Start querying with your token Access keys, Google sign-in, bearer tokens --- # Quickstart Source: https://docs.xpoz.ai/quickstart ## 1. Get your access key Sign up at [xpoz.ai](https://xpoz.ai) and get your access key from the dashboard. A free tier is available. ## 2. Choose your integration ```bash claude mcp add xpoz-mcp https://mcp.xpoz.ai/mcp \ -t http \ -H "Authorization: Bearer YOUR_API_KEY" ``` That's it. Ask Claude to search social media: ``` Search Twitter for posts about "artificial intelligence" from the last week ``` ```bash npm install @xpoz/xpoz ``` ```typescript import { XpozClient } from '@xpoz/xpoz'; const client = new XpozClient({ apiKey: 'YOUR_API_KEY' }); const user = await client.twitter.getUser({ identifier: 'elonmusk', identifierType: 'username' }); console.log(user.name, user.followersCount); ``` ```bash pip install xpoz ``` ```python from xpoz import XpozClient client = XpozClient(api_key="YOUR_API_KEY") user = client.twitter.get_user( identifier="elonmusk", identifier_type="username" ) print(user.name, user.followers_count) ``` ```bash # Install brew install xpoz-ai/tap/xpoz-cli # Authenticate xpoz-cli auth login # Search xpoz-cli twitter get_user --identifier elonmusk ``` ## 3. Try a search Here are some queries to get you started: Ask your AI agent: ``` Search Twitter for posts about "machine learning" from the last 30 days ``` ```typescript const results = await client.twitter.searchPosts({ query: 'machine learning', startDate: '2025-01-01', responseType: 'fast' }); for (const post of results.data) { console.log(post.text, post.retweetCount); } ``` ```python results = client.twitter.search_posts( query="machine learning", start_date="2025-01-01", response_type="fast" ) for post in results.data: print(post.text, post.retweet_count) ``` ```typescript const user = await client.instagram.getUser({ identifier: 'natgeo', identifierType: 'username' }); console.log(user.fullName, user.followerCount); ``` ```python user = client.instagram.get_user( identifier="natgeo", identifier_type="username" ) print(user.full_name, user.follower_count) ``` ```typescript const results = await client.reddit.searchPosts({ query: 'python best practices', subreddit: 'learnpython', responseType: 'fast' }); ``` ```python results = client.reddit.search_posts( query="python best practices", subreddit="learnpython", response_type="fast" ) ``` ## 4. Set up continuous tracking Xpoz can continuously monitor keywords, users, subreddits, and hashtags you care about. Continuous tracking gives you **better data coverage** and **fresher results**. Ask your AI agent: ``` Track the keyword "artificial intelligence" on Twitter and Reddit, and track the user "openai" on Twitter ``` ```typescript await client.tracking.addTrackedItems({ items: [ { phrase: "artificial intelligence", type: "keyword", platform: "twitter" }, { phrase: "artificial intelligence", type: "keyword", platform: "reddit" }, { phrase: "openai", type: "user", platform: "twitter" }, ] }); ``` ```python client.tracking.add_tracked_items(items=[ {"phrase": "artificial intelligence", "type": "keyword", "platform": "twitter"}, {"phrase": "artificial intelligence", "type": "keyword", "platform": "reddit"}, {"phrase": "openai", "type": "user", "platform": "twitter"}, ]) ``` ```bash xpoz-cli tracking add_tracked_items \ --items '[{"phrase":"artificial intelligence","type":"keyword","platform":"twitter"},{"phrase":"artificial intelligence","type":"keyword","platform":"reddit"}]' ``` You can track keywords and users on all platforms, subreddits on Reddit, and hashtags on TikTok. See the [Tracking Guide](/guides/tracking) for best practices and common workflows. ## Next steps Learn about access keys, Google sign-in, and bearer tokens Browse all 48 available tools Best practices for continuous tracking Master search with boolean operators --- # Authentication Source: https://docs.xpoz.ai/authentication Every request to Xpoz requires authentication. Choose the method that fits your use case: | Method | Best for | Complexity | |--------|----------|------------| | **Trial Token** | Instant access, no sign-up needed | Simplest | | **Access Key** | SDKs, CLI, scripts, quick prototyping | Simplest | | **Google Sign-In** | Claude Desktop, browser-based clients | Automatic | | **Bearer Token** | Claude Code, N8N, programmatic MCP access | One-time setup | ## Credential precedence When multiple credentials are available, Xpoz resolves them in this order: 1. **Explicit parameter** passed to the client constructor (`apiKey` / `api_key`) 2. **Environment variable** (`XPOZ_API_KEY`) 3. **Stored configuration** (from CLI `auth login` or prior sign-in) ## Instant access — no sign-up Get a working API key in two HTTP calls — no signup, no approval, no waiting. Perfect for agents that need social media data right now. ### Step 1: Generate a free token ```bash curl -s -X POST https://api.xpoz.ai/api/trial/token \ -H "Content-Type: application/json" \ -d '{"source": ""}' | jq -r .data.accessKey # -> TRIAL... (valid 5 days) ``` ### Step 2: Use it as your API key Pass the `TRIAL...` token exactly like an access key — as the SDK `apiKey`, the `XPOZ_API_KEY` env var, or a bearer token. All read tools work immediately across all four platforms. ```bash export XPOZ_API_KEY=TRIAL... xpoz-cli twitter get_user --identifier elonmusk ``` Instant access tokens return up to 5 results per call. For full result sets, pagination, CSV export, and live crawling, [get a free access key](https://xpoz.ai/get-token) — still no credit card. Same API shape, nothing to rewrite. ## Access Key authentication The simplest way to authenticate. Get your key and start querying immediately. ### Step 1: Get your access key Sign up at [xpoz.ai](https://xpoz.ai) and navigate to the dashboard. Your access key is available on the **Get Token** page at [xpoz.ai/get-token](https://xpoz.ai/get-token). ### Step 2: Use the key Pass the key directly or set it as an environment variable: ```bash export XPOZ_API_KEY=your-api-key ``` ```typescript import { XpozClient } from '@xpoz/xpoz'; const client = new XpozClient({ apiKey: 'your-api-key' }); await client.connect(); ``` ```python from xpoz import XpozClient client = XpozClient("your-api-key") ``` ```bash export XPOZ_API_KEY=your-api-key xpoz-cli twitter get_user --identifier elonmusk ``` Never commit access keys to version control. Use environment variables or a secrets manager in production. ## Google Sign-In When you connect via Claude Desktop or other browser-based MCP clients, authentication happens automatically through Google Sign-In. ### How it works 1. Your MCP client (e.g., Claude Desktop) initiates the sign-in flow when connecting to Xpoz 2. A Google sign-in prompt appears in your browser 3. After signing in, the connection is established automatically 4. All subsequent requests are authenticated — no manual token management required This is the recommended method for Claude Desktop. Just add the Xpoz MCP server and the sign-in flow handles everything. See [Installation](/mcp/installation) for step-by-step setup with Claude Desktop. ## Bearer token authentication For programmatic access from Claude Code, N8N, or any HTTP client. Pass your access key as a bearer token in the `Authorization` header. ### Get your access key Sign up at [xpoz.ai](https://xpoz.ai) and copy your access key from the dashboard. ### Connect from your client ```bash claude mcp add xpoz-mcp https://mcp.xpoz.ai/mcp \ -t http \ -H "Authorization: Bearer YOUR_API_KEY" ``` Create an **AI Agent** node and add a **Tool** > **MCP Client Tool**: - **Endpoint**: `https://mcp.xpoz.ai/mcp` - **Server Transport**: HTTP Streamable - **Authentication Type**: Bearer Auth - **Credential for Bearer Auth**: Your access key If you can see the tools list, you are connected. Include the bearer token in the `Authorization` header: ```bash curl -X POST https://mcp.xpoz.ai/mcp \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{"jsonrpc":"2.0","method":"tools/call","params":{"name":"getTwitterUser","arguments":{"identifier":"elonmusk","identifierType":"username"}},"id":1}' ``` ## Next steps Start querying with your credentials Browse all 48 available tools --- # Pricing & Credits Source: https://docs.xpoz.ai/pricing Every Xpoz plan includes credits. Credits are spent per search, not per result: a search costs a flat number of credits based on the platform, and returns up to 300 results at no extra charge. You pay for the questions you ask, not the data you get back. ## What a search costs | Platform | Credits per search | | --------- | ------------------ | | Reddit | 2 | | Twitter/X | 2 | | TikTok | 5 | | Instagram | 12 | Only data queries spend credits. Account, tracking, auth, and operation tools (`getAccountDetails`, `getCreditsUsageHistory`, `getTrackedItems`, `addTrackedItems`, `removeTrackedItems`, `checkOperationStatus`, and the rest) are always free. Each tool call is charged, including pagination: fetching page 2 of a paged result set is a new call at the same platform rate. Fast mode returns up to 300 results in a single call, so it is the most credit-efficient way to search. See [Response Modes](/mcp/response-modes). ## Plans | Plan | Price | Credits | Extra credits | | ---------- | ---------------------------- | ---------------- | ------------- | | Free | \$0 | 500 (one-time) | — | | Pro | \$20/mo (\$16/mo billed annually) | 30,000/month | \$0.80 per 1,000 | | Max | \$200/mo (\$160/mo billed annually) | 600,000/month | \$0.40 per 1,000 | | Enterprise | Custom | Custom | Custom | Free tier credits are a one-time allocation and do not refresh. When they run out, Free users hit a hard stop; Pro and Max users continue at the extra-credit rate, or can upgrade at any time. ## What credits translate to A search returns up to 300 results for a flat credit price, so credits go a long way: up to 5 million results per month on Pro, and up to 100 million results per month on Max. ## CSV export rows CSV export is the one place rows are metered separately from credits. An export is charged twice: the query itself at the normal platform rate (2-12 credits), plus every exported row against your plan's row allowance: | Plan | Included export rows | Extra rows | | ---- | --------------------------- | --------------- | | Free | 10,000 total (500 per file) | — | | Pro | 50,000/month | \$1 per 1,000 | | Max | 250,000/month | \$1 per 1,000 | See [CSV Exports](/guides/csv-exports) for how exports work. ## Tracked keywords and users [Continuous tracking](/tracking) slots per plan: | Plan | Tracked keywords/users | Extra slots | | ---------- | ---------------------- | ------------------ | | Free | 1 | — | | Pro | 10 | \$5 per keyword/user | | Max | 30 | \$2 per keyword/user | | Enterprise | Unlimited | — | ## Instant access costs nothing [Instant access tokens](/trial) spend no credits at all. They return up to 5 results per call for 5 days — enough to evaluate the data before creating an account. ## Check your usage Ask your agent, or check the [usage dashboard](https://xpoz.ai/usage): - `getAccountDetails` — plan, billing, and remaining subscription and extra credits - `getCreditsUsageHistory` — credits and export rows spent over time, by hour or day Both are documented in [Account Tools](/mcp/tools/account). Full plan comparison and checkout on xpoz.ai Get your access key and run your first search --- # Query Syntax Source: https://docs.xpoz.ai/guides/query-syntax All `search*` and `get*ByKeywords` methods across every platform accept a `query` parameter that supports Lucene-style full-text search. This guide covers every operator with practical examples. ## Basic syntax ### Plain text (OR by default) Space-separated terms without quotes match posts containing **any** of the words. A bare space is treated as `OR`: ``` AI crypto blockchain ``` This returns posts containing "AI" **or** "crypto" **or** "blockchain". Because bare spaces default to OR, always use explicit `AND` when you need all terms present. ### Exact phrases Wrap terms in double quotes to match the exact phrase: ``` "machine learning" "climate change" "artificial intelligence" ``` Only posts containing the exact phrase (in that word order) are returned. ## Boolean operators Use `AND` and `OR` to combine terms. Operators are **case-insensitive** (`and`, `AND`, `And` all work). ### AND -- both terms required ``` AI AND robotics "deep learning" AND python Tesla AND "quarterly earnings" ``` ### OR -- either term matches ``` Tesla OR SpaceX pytorch OR tensorflow "machine learning" OR "deep learning" ``` ## Grouping with parentheses Combine operators with parentheses for complex queries: ``` (AI OR ML) AND (healthcare OR medical) (AI OR "artificial intelligence") AND ethics ("machine learning" OR "deep learning") AND python ``` ## Common patterns | Use case | Query | |----------|-------| | Brand monitoring | `"your brand" OR @yourbrand` | | Competitor comparison | `(CompanyA OR CompanyB) AND "product launch"` | | Sentiment on a topic | `"electric vehicles" AND (love OR hate OR amazing OR terrible)` | | Industry trends | `("generative AI" OR "large language models") AND 2025` | | Job market signals | `(hiring OR "open role") AND "data scientist"` | | Academic research | `"climate change" AND (study OR research OR paper)` | | Product feedback | `"your product" AND (bug OR issue OR broken OR love OR amazing)` | ## SDK examples ```typescript import { XpozClient, ResponseType } from '@xpoz/xpoz'; const client = new XpozClient({ apiKey: 'your-api-key' }); await client.connect(); // Exact phrase with boolean operators const results = await client.twitter.searchPosts( '("machine learning" OR "deep learning") AND python ', { startDate: '2025-01-01', language: 'en', responseType: ResponseType.Fast, limit: 50, fields: ['id', 'text', 'likeCount', 'authorUsername', 'createdAtDate'], } ); for (const post of results.data) { console.log(`@${post.authorUsername}: ${post.text}`); } await client.close(); ``` ```python from xpoz import XpozClient, ResponseType with XpozClient("your-api-key") as client: results = client.twitter.search_posts( '("machine learning" OR "deep learning") AND python ', start_date="2025-01-01", language="en", response_type=ResponseType.FAST, limit=50, fields=["id", "text", "like_count", "author_username", "created_at_date"], ) for post in results.data: print(f"@{post.author_username}: {post.text}") ``` Ask your AI agent: ``` Search Twitter for posts matching ("machine learning" OR "deep learning") AND python , from the last 30 days, in English. Show me the top 50 results with author, text, and like count. ``` ## Multi-platform search The same query syntax works across all platforms. Platform behavior is consistent, but content differs: | Platform | Search methods | |----------|---------------| | Twitter/X | `searchPosts`, `getUsersByKeywords` | | Instagram | `searchPosts`, `getUsersByKeywords` | | Reddit | `searchPosts`, `searchComments`, `getUsersByKeywords`, `getSubredditsByKeywords` | | TikTok | `searchPosts`, `getUsersByKeywords` | ## Combining with dedicated parameters Do **not** embed platform-specific operators in the query string. Use the dedicated parameters instead: | Instead of... | Use parameter | |---------------|---------------| | `from:elonmusk` | `authorUsername: "elonmusk"` (TS) / `author_username="elonmusk"` (Python) | | `lang:en` | `language: "en"` (TS) / `language="en"` (Python) | | `since:2025-01-01` | `startDate: "2025-01-01"` (TS) / `start_date="2025-01-01"` (Python) | | `until:2025-06-01` | `endDate: "2025-06-01"` (TS) / `end_date="2025-06-01"` (Python) | ```typescript const results = await client.twitter.searchPosts( '"artificial intelligence" AND ethics', { startDate: '2025-01-01', endDate: '2025-06-01', language: 'en', fields: ['id', 'text', 'likeCount', 'authorUsername'], } ); ``` ```python results = client.twitter.search_posts( '"artificial intelligence" AND ethics', start_date="2025-01-01", end_date="2025-06-01", language="en", fields=["id", "text", "like_count", "author_username"], ) ``` ## Reddit-specific filters Reddit search methods accept additional parameters for sorting and time filtering: ```typescript const results = await client.reddit.searchPosts('python tutorial', { subreddit: 'learnpython', sort: 'top', time: 'month', responseType: ResponseType.Fast, limit: 25, }); ``` ```python results = client.reddit.search_posts( "python tutorial", subreddit="learnpython", sort="top", time="month", response_type=ResponseType.FAST, limit=25, ) ``` Reddit sort options: `relevance`, `hot`, `top`, `new`, `comments`. Time filters: `hour`, `day`, `week`, `month`, `year`, `all`. ## Common mistakes **Forgetting quotes for exact phrases:** - `machine learning` matches "machine" OR "learning" (two separate words) - `"machine learning"` matches the exact phrase **Implicit OR behavior:** - `AI blockchain crypto` returns posts with ANY of these terms - `AI AND blockchain AND crypto` returns posts with ALL three terms **Nested parentheses:** - Keep grouping to one level of nesting for best results - `(A OR B) AND (C OR D)` works well - Deeply nested queries may produce unexpected results **Empty results:** - Broaden your date range or remove restrictive filters - Try fewer AND conditions - Check spelling of exact phrases ## Next steps Choose fast, paging, or CSV for your queries Reduce response size by selecting specific fields Export large result sets to CSV Optimize queries for performance --- # CSV Exports Source: https://docs.xpoz.ai/guides/csv-exports Xpoz supports bulk data export to CSV for any search or paginated query. Instead of iterating through hundreds of pages, export the entire result set as a single downloadable file hosted on S3. ## How it works 1. Set the response mode to **CSV** 2. The server runs the query asynchronously and writes results to S3 3. You receive an S3 download URL when the export completes 4. Download the CSV file for analysis, reporting, or archival CSV exports can contain up to **500,000 rows**. For larger datasets, use date range filters to split your export into smaller batches. ## SDK usage ### Direct CSV mode Set `responseType: ResponseType.Csv` to initiate a CSV export directly: ```typescript import { XpozClient, ResponseType } from '@xpoz/xpoz'; const client = new XpozClient({ apiKey: 'your-api-key' }); await client.connect(); const results = await client.twitter.searchPosts('bitcoin', { startDate: '2025-01-01', responseType: ResponseType.Csv, }); // Poll the export operation and get the download URL const downloadUrl = await results.exportCsv(); console.log('Download:', downloadUrl); await client.close(); ``` ### Export from a paginated result Start with paging mode, review the first page, then export if needed: ```typescript const results = await client.twitter.searchPosts('AI', { startDate: '2025-01-01', responseType: ResponseType.Paging, }); console.log(`${results.pagination.totalRows} total results`); // Decide to export after seeing the count if (results.pagination.totalRows > 1000) { const csvUrl = await results.exportCsv(); console.log('Exported to:', csvUrl); } ``` ### Direct CSV mode Set `response_type=ResponseType.CSV` to initiate a CSV export directly: ```python from xpoz import XpozClient, ResponseType with XpozClient("your-api-key") as client: results = client.twitter.search_posts( "bitcoin", start_date="2025-01-01", response_type=ResponseType.CSV, ) # Poll the export operation and get the download URL download_url = results.export_csv() print(f"Download: {download_url}") ``` ### Export from a paginated result Start with paging mode, review the first page, then export if needed: ```python results = client.twitter.search_posts( "AI", start_date="2025-01-01", response_type=ResponseType.PAGING, ) print(f"{results.pagination.total_rows} total results") if results.pagination.total_rows > 1000: csv_url = results.export_csv() print(f"Exported to: {csv_url}") ``` ### Async client ```python import asyncio from xpoz import AsyncXpozClient, ResponseType async def export_data(): async with AsyncXpozClient("your-api-key") as client: results = await client.twitter.search_posts( "bitcoin", start_date="2025-01-01", response_type=ResponseType.CSV, ) download_url = await results.export_csv() print(f"Download: {download_url}") asyncio.run(export_data()) ``` Use the `--export-csv-url` flag to export results to CSV: ```bash xpoz-cli twitter search_posts \ --query "bitcoin" \ --start-date 2025-01-01 \ --export-csv-url ``` The CLI prints the S3 download URL when the export completes. Pipe it to `curl` or `wget` to download: ```bash URL=$(xpoz-cli twitter search_posts \ --query "bitcoin" \ --start-date 2025-01-01 \ --export-csv-url) curl -o bitcoin_tweets.csv "$URL" ``` ## CSV file format The exported CSV file includes: - **Header row** with column names matching the API field names - **UTF-8 encoding** for international characters - **Standard CSV escaping** (quoted fields for values containing commas or newlines) - **All available fields** unless you specified `fields` in the original query Use the `fields` parameter in your query to control which columns appear in the CSV. This reduces file size and speeds up the export. ## Methods supporting CSV export | Platform | Method | SDK (TS) | SDK (Python) | |----------|--------|----------|-------------| | Twitter | Search posts | `twitter.searchPosts()` | `twitter.search_posts()` | | Twitter | Posts by author | `twitter.getPostsByAuthor()` | `twitter.get_posts_by_author()` | | Twitter | Users by keywords | `twitter.getUsersByKeywords()` | `twitter.get_users_by_keywords()` | | Instagram | Search posts | `instagram.searchPosts()` | `instagram.search_posts()` | | Instagram | Posts by user | `instagram.getPostsByUser()` | `instagram.get_posts_by_user()` | | Instagram | Users by keywords | `instagram.getUsersByKeywords()` | `instagram.get_users_by_keywords()` | | Reddit | Search posts | `reddit.searchPosts()` | `reddit.search_posts()` | | TikTok | Search posts | `tiktok.searchPosts()` | `tiktok.search_posts()` | | TikTok | Posts by user | `tiktok.getPostsByUser()` | `tiktok.get_posts_by_user()` | | TikTok | Users by keywords | `tiktok.getUsersByKeywords()` | `tiktok.get_users_by_keywords()` | | TikTok | Posts by hashtags | `tiktok.getPostsByHashtags()` | `tiktok.get_posts_by_hashtags()` | | TikTok | Users by hashtags | `tiktok.getUsersByHashtags()` | `tiktok.get_users_by_hashtags()` | ## Use cases - **Data analysis**: Import into pandas, Excel, or Google Sheets for in-depth analysis - **Reporting**: Generate periodic reports on brand mentions, sentiment, or engagement - **Archival**: Store snapshots of social media data for compliance or research - **ML training**: Build training datasets for sentiment analysis, topic classification, or trend prediction - **Cross-platform comparison**: Export data from multiple platforms and join in your analytics tool ## Next steps Compare fast, paging, and CSV modes Optimize queries and exports for performance --- # Continuous Tracking Source: https://docs.xpoz.ai/tracking ## What is continuous tracking? Continuous tracking lets you register keywords, users, subreddits, and hashtags that Xpoz monitors on a regular schedule. This results in: - **Better coverage** — regular monitoring captures more posts and updates, so your search results are more complete - **Fresher data** — tracked items are kept up to date, so you always get the most recent content ## How it works Use `addTrackedItems` (MCP tool) or `client.tracking.addTrackedItems()` (SDK) to register keywords, users, subreddits, or hashtags for continuous tracking. Xpoz regularly collects new data for your tracked items across all configured platforms. When you search for tracked keywords or query tracked users, you get broader coverage and fresher content. ## What can you track? Every tracked item has three fields: `phrase` (the term to track), `type` (what kind of item), and `platform` (which social network). | Type | Description | Example `phrase` | |------|-------------|-----------------| | `keyword` | A search term in post content | `"artificial intelligence"`, `"Tesla"` | | `user` | A social media account by username | `"elonmusk"`, `"natgeo"` | | `subreddit` | A Reddit community (Reddit-only) | `"wallstreetbets"`, `"MachineLearning"` | | `hashtag` | A TikTok hashtag (TikTok-only) | `"fyp"`, `"sustainable_fashion"` | ### Platform compatibility | Type | Twitter/X | Instagram | Reddit | TikTok | |------|-----------|-----------|--------|--------| | `keyword` | Yes | Yes | Yes | Yes | | `user` | Yes | Yes | Yes | Yes | | `subreddit` | — | — | Yes | — | | `hashtag` | — | — | — | Yes | ## Best practices ### Track strategically Your plan has a limited number of tracking slots. Focus on high-value terms that you query regularly rather than tracking everything. - **Track your brand** as a keyword on all four platforms — this is the most common use case - **Track competitor accounts** as users to monitor their posting activity - **Track relevant subreddits** where your industry or product is discussed - **Track campaign hashtags** on TikTok for time-limited campaigns ### Manage your tracked items - Call `getTrackedItems` before removing items — the `phrase`, `type`, and `platform` must match exactly - Use `getAccountDetails` to check your plan's tracking limit and current usage - Remove tracked items you no longer need to free up slots for new ones ### Choose the right type - Use `keyword` for topics and phrases — this tracks posts containing those words - Use `user` for specific accounts — this tracks their posting activity - Use `subreddit` for Reddit communities — this tracks all posts in that subreddit - Use `hashtag` for TikTok campaigns — this is more precise than keyword search for hashtag matching ## Common workflows ### Brand monitoring across platforms Ask your AI agent: ``` Track my brand "Acme Corp" as a keyword on Twitter, Instagram, Reddit, and TikTok. Also track our official accounts @acmecorp on Twitter and Instagram. ``` ```typescript await client.tracking.addTrackedItems({ items: [ { phrase: "Acme Corp", type: "keyword", platform: "twitter" }, { phrase: "Acme Corp", type: "keyword", platform: "instagram" }, { phrase: "Acme Corp", type: "keyword", platform: "reddit" }, { phrase: "Acme Corp", type: "keyword", platform: "tiktok" }, { phrase: "acmecorp", type: "user", platform: "twitter" }, { phrase: "acmecorp", type: "user", platform: "instagram" }, ] }); ``` ```python client.tracking.add_tracked_items(items=[ {"phrase": "Acme Corp", "type": "keyword", "platform": "twitter"}, {"phrase": "Acme Corp", "type": "keyword", "platform": "instagram"}, {"phrase": "Acme Corp", "type": "keyword", "platform": "reddit"}, {"phrase": "Acme Corp", "type": "keyword", "platform": "tiktok"}, {"phrase": "acmecorp", "type": "user", "platform": "twitter"}, {"phrase": "acmecorp", "type": "user", "platform": "instagram"}, ]) ``` ```bash xpoz-cli tracking add_tracked_items \ --items '[{"phrase":"Acme Corp","type":"keyword","platform":"twitter"},{"phrase":"Acme Corp","type":"keyword","platform":"instagram"},{"phrase":"Acme Corp","type":"keyword","platform":"reddit"},{"phrase":"Acme Corp","type":"keyword","platform":"tiktok"}]' ``` ### Competitor tracking ```typescript await client.tracking.addTrackedItems({ items: [ { phrase: "CompetitorBrand", type: "keyword", platform: "twitter" }, { phrase: "CompetitorBrand", type: "keyword", platform: "reddit" }, { phrase: "competitor_official", type: "user", platform: "twitter" }, { phrase: "competitor_official", type: "user", platform: "instagram" }, ] }); ``` Then periodically search and compare using the [Competitive Intelligence](/skills/competitive-intel) skill. ### Reddit community monitoring ```typescript await client.tracking.addTrackedItems({ items: [ { phrase: "MachineLearning", type: "subreddit", platform: "reddit" }, { phrase: "artificial", type: "subreddit", platform: "reddit" }, { phrase: "machine learning", type: "keyword", platform: "reddit" }, ] }); ``` ### TikTok hashtag campaign ```typescript await client.tracking.addTrackedItems({ items: [ { phrase: "myBrandChallenge", type: "hashtag", platform: "tiktok" }, { phrase: "my brand challenge", type: "keyword", platform: "tiktok" }, { phrase: "mybrand", type: "user", platform: "tiktok" }, ] }); ``` Track both the hashtag and related keywords. Users don't always include the hashtag, so keyword tracking captures posts that reference the campaign without tagging it. ### Listing and removing items ```typescript const tracked = await client.tracking.getTrackedItems(); console.log(tracked); await client.tracking.removeTrackedItems({ items: [ { phrase: "old_keyword", type: "keyword", platform: "twitter" } ] }); ``` ```python tracked = client.tracking.get_tracked_items() print(tracked) client.tracking.remove_tracked_items(items=[ {"phrase": "old_keyword", "type": "keyword", "platform": "twitter"} ]) ``` ```bash xpoz-cli tracking get_tracked_items xpoz-cli tracking remove_tracked_items \ --items '[{"phrase":"old_keyword","type":"keyword","platform":"twitter"}]' ``` ## Related MCP tool reference for getTrackedItems, addTrackedItems, removeTrackedItems Pre-built AI skill for managing tracked items Check your plan limits and tracking usage --- # Best Practices Source: https://docs.xpoz.ai/guides/best-practices Follow these recommendations to get the most out of Xpoz's API, whether you are building an AI agent, a data pipeline, or an interactive application. ## Use field selection Always specify the `fields` parameter to retrieve only the data you need. This dramatically improves response time and reduces memory usage. ```typescript // Slow: returns all 20+ fields per post const results = await client.twitter.searchPosts('AI'); // Fast: returns only what you need const results = await client.twitter.searchPosts('AI', { fields: ['id', 'text', 'likeCount', 'authorUsername', 'createdAtDate'], }); ``` ```python # Slow: returns all 20+ fields per post results = client.twitter.search_posts("AI") # Fast: returns only what you need results = client.twitter.search_posts( "AI", fields=["id", "text", "like_count", "author_username", "created_at_date"], ) ``` For engagement analysis, use `["id", "text", "likeCount", "retweetCount", "replyCount", "createdAtDate"]`. For user discovery, use `["id", "username", "name", "followersCount", "description"]`. ## Choose the right response mode | Mode | When to use | Rows returned | |------|-------------|---------------| | **Fast** (default) | Quick lookups, UI previews, agent queries | Up to 300 | | **Paging** | Iterating through full result sets | 100 per page, unlimited total | | **CSV** | Bulk exports, data analysis, archival | Up to 500K | ```typescript import { ResponseType } from '@xpoz/xpoz'; // Quick lookup: get top 50 results immediately const fast = await client.twitter.searchPosts('AI', { responseType: ResponseType.Fast, limit: 50, }); // Full iteration: paginate through all results const paged = await client.twitter.searchPosts('AI', { responseType: ResponseType.Paging, }); // Bulk export: download as CSV const csv = await client.twitter.searchPosts('AI', { responseType: ResponseType.Csv, }); const url = await csv.exportCsv(); ``` ```python from xpoz import ResponseType # Quick lookup fast = client.twitter.search_posts("AI", response_type=ResponseType.FAST, limit=50) # Full iteration paged = client.twitter.search_posts("AI", response_type=ResponseType.PAGING) # Bulk export csv = client.twitter.search_posts("AI", response_type=ResponseType.CSV) url = csv.export_csv() ``` ## Pagination patterns Do not fetch all pages unless you actually need the full dataset. Common patterns: ### Sample the first page, then decide ```typescript const results = await client.twitter.searchPosts('bitcoin', { responseType: ResponseType.Paging, }); console.log(`Total: ${results.pagination.totalRows} results`); // Only fetch more if needed if (results.pagination.totalRows < 500) { let page = results; while (page.hasNextPage()) { page = await page.nextPage(); // process page.data } } else { // Too many results -- export to CSV instead const csvUrl = await results.exportCsv(); } ``` ```python results = client.twitter.search_posts("bitcoin", response_type=ResponseType.PAGING) print(f"Total: {results.pagination.total_rows} results") if results.pagination.total_rows < 500: page = results while page.has_next_page(): page = page.next_page() # process page.data else: csv_url = results.export_csv() ``` ### Jump to a specific page ```typescript const page5 = await results.getPage(5); ``` ```python page5 = results.get_page(5) ``` ## Query optimization ### Be specific with keywords ``` // Too broad: returns millions of results "AI" // Better: narrow with boolean operators "AI" AND "healthcare" AND 2025 // Best: exact phrases with filters "AI-powered diagnostics" AND (healthcare OR medical) ``` ### Use date ranges Always include `startDate` (and optionally `endDate`) to limit results to a relevant time window: ```typescript const results = await client.twitter.searchPosts('AI', { startDate: '2025-06-01', endDate: '2025-06-15', }); ``` ```python results = client.twitter.search_posts("AI", start_date="2025-06-01", end_date="2025-06-15") ``` ### Use platform-specific filters Do not embed filters in the query string. Use dedicated parameters: | Parameter | TypeScript | Python | |-----------|-----------|--------| | Author filter | `authorUsername: "elonmusk"` | `author_username="elonmusk"` | | Language filter | `language: "en"` | `language="en"` | | Subreddit filter | `subreddit: "learnpython"` | `subreddit="learnpython"` | | Reddit sort | `sort: "top"` | `sort="top"` | | Reddit time | `time: "month"` | `time="month"` | ## Error handling Build retry logic for timeouts and transient failures: ```typescript import { XpozError, AuthenticationError, OperationTimeoutError, OperationFailedError, } from '@xpoz/xpoz'; async function searchWithRetry(query: string, retries = 2) { for (let attempt = 0; attempt <= retries; attempt++) { try { return await client.twitter.searchPosts(query, { responseType: ResponseType.Fast, limit: 100, }); } catch (e) { if (e instanceof AuthenticationError) { throw e; // Don't retry auth errors } if (e instanceof OperationTimeoutError && attempt < retries) { console.log(`Attempt ${attempt + 1} timed out, retrying...`); continue; } throw e; } } } ``` ```python from xpoz import ( AuthenticationError, OperationTimeoutError, XpozError, ResponseType, ) def search_with_retry(query: str, retries: int = 2): for attempt in range(retries + 1): try: return client.twitter.search_posts( query, response_type=ResponseType.FAST, limit=100, ) except AuthenticationError: raise # Don't retry auth errors except OperationTimeoutError: if attempt < retries: print(f"Attempt {attempt + 1} timed out, retrying...") continue raise ``` Authentication errors (`401`) should never be retried. Timeout errors are safe to retry. Failed operations may indicate a server-side issue -- check the `operationError` field for details. ## Caching Xpoz caches operation results server-side with a TTL: - **Running operations**: 30-minute TTL (auto-expire if stalled) - **Completed operations**: 15-minute TTL (retrieve results within this window) - **Paginated tables**: Remain available for page navigation after creation For paging mode, the first call creates a server-side table with all results. Subsequent `nextPage()` and `getPage(n)` calls read from this cached table, making page navigation fast. ## Client lifecycle Always close the client when done to release resources: ```typescript // Option 1: async disposal (Node.js 18.2+) await using client = new XpozClient({ apiKey: 'key' }); await client.connect(); // client.close() called automatically // Option 2: try/finally const client = new XpozClient({ apiKey: 'key' }); await client.connect(); try { const user = await client.twitter.getUser('elonmusk'); } finally { await client.close(); } ``` ```python # Option 1: context manager with XpozClient("key") as client: user = client.twitter.get_user("elonmusk") # client.close() called automatically # Option 2: async context manager async with AsyncXpozClient("key") as client: user = await client.twitter.get_user("elonmusk") ``` ## Summary checklist - Always specify `fields` to reduce response size - Use `Fast` mode for quick lookups, `Paging` for iteration, `CSV` for bulk export - Include date ranges to narrow results - Use dedicated filter parameters instead of embedding filters in queries - Handle `AuthenticationError` and `OperationTimeoutError` separately - Close the client when done ## Next steps Master boolean operators and phrase matching Export large datasets for offline analysis Full list of available fields per platform Browse all 48 available tools --- # Xpoz MCP Server Source: https://docs.xpoz.ai/mcp/overview The Xpoz MCP server provides AI agents with structured access to social media data across four platforms. It exposes **48 tools** that let agents search posts, look up users, analyze engagement, and export data -- all through the standard [Model Context Protocol](https://modelcontextprotocol.io/). ## Key Features Twitter/X, Instagram, Reddit, and TikTok -- users, posts, comments, connections, and subreddits. Efficient pagination with cached tables -- 100 items per page, iterate through large result sets without re-querying. Choose between fast (immediate results), paging (iterate through pages), and CSV (bulk export up to 500K rows). Request only the fields you need to reduce response size and improve performance. ## Platform Coverage | Platform | Users | Posts | Comments | Other | |---|---|---|---|---| | **Twitter/X** | 5 tools | 8 tools | -- | -- | | **Instagram** | 5 tools | 3 tools | 1 tool | -- | | **Reddit** | 3 tools | 2 tools | 1 tool | 3 subreddit tools | | **TikTok** | 4 tools | 4 tools | 1 tool | -- | | **Tracking** | -- | -- | -- | 3 tools | | **Account** | -- | -- | -- | 3 tools | ## How It Works ``` Your AI Agent (Claude, Gemini, Cursor, N8N, etc.) │ │ MCP Protocol ▼ ┌─────────────────────┐ │ Xpoz MCP Server │ │ mcp.xpoz.ai/mcp │ │ │ │ 48 tools across │ │ 4 platforms │ └─────────┬───────────┘ │ ▼ ┌─────────────────────┐ │ Xpoz Data Platform │ │ Billions of posts │ │ and users │ └─────────────────────┘ ``` Your AI agent connects to the hosted Xpoz MCP server at `https://mcp.xpoz.ai/mcp` using your access key. The server handles data retrieval, pagination, caching, and data freshness -- your agent just calls tools and gets structured results. ## Next Steps Connect the MCP server to your preferred AI client. See all 48 tools organized by platform. Learn when to use fast, paging, or CSV mode. Optimize performance by requesting only the fields you need. --- # Installation Source: https://docs.xpoz.ai/mcp/installation The Xpoz MCP server is hosted at `https://mcp.xpoz.ai/mcp`. You need an access key to authenticate -- get one from your [Xpoz dashboard](https://xpoz.ai). **Start instantly — no account needed.** Generate a free token and use it in place of `YOUR_API_KEY` below: ```bash curl -s -X POST https://api.xpoz.ai/api/trial/token \ -H "Content-Type: application/json" \ -d '{"source": ""}' | jq -r .data.accessKey # -> TRIAL... (valid 5 days, all read tools across 4 platforms) ``` This returns a preview of up to 5 results per call. To get full data, pagination, and CSV export, [create a free account](https://xpoz.ai/get-token) — no credit card required. Run a single command in your terminal: ```bash claude mcp add xpoz-mcp https://mcp.xpoz.ai/mcp -t http -H "Authorization: Bearer YOUR_API_KEY" ``` Claude Code will automatically discover all 48 tools on the next conversation. You can verify the connection by asking Claude: "What Xpoz tools are available?" 1. Open Claude Desktop 2. Go to **Settings** > **Developer** > **Edit Config** 3. Add the following to your configuration file: ```json { "mcpServers": { "xpoz": { "url": "https://mcp.xpoz.ai/mcp", "headers": { "Authorization": "Bearer YOUR_API_KEY" } } } } ``` 4. Restart Claude Desktop Replace `YOUR_API_KEY` with your actual Xpoz access key. You can find it in your [Xpoz dashboard](https://xpoz.ai). Add the MCP server to your Gemini CLI settings file (`~/.gemini/settings.json`): ```json { "mcpServers": { "xpoz": { "uri": "https://mcp.xpoz.ai/mcp", "headers": { "Authorization": "Bearer YOUR_API_KEY" } } } } ``` Restart Gemini CLI to pick up the new configuration. 1. Open Cursor Settings (`Cmd+,` / `Ctrl+,`) 2. Navigate to **MCP** section 3. Click **Add new MCP server** 4. Configure: - **Name**: `xpoz` - **Type**: `http` - **URL**: `https://mcp.xpoz.ai/mcp` Alternatively, add to your `.cursor/mcp.json`: ```json { "mcpServers": { "xpoz": { "url": "https://mcp.xpoz.ai/mcp", "headers": { "Authorization": "Bearer YOUR_API_KEY" } } } } ``` Set the `Authorization` header with your bearer token. Cursor supports HTTP transport natively. 1. Create an **AI Agent** node in your workflow 2. Add a tool: **MCP Client Tool** 3. Configure the MCP Client Tool: | Setting | Value | |---|---| | **Endpoint** | `https://mcp.xpoz.ai/mcp` | | **Server Transport** | HTTP Streamable | | **Authentication Type** | Bearer Auth | | **Credential for Bearer Auth** | Your Xpoz access key | 4. Click **Refresh** to load the available tools 5. Select which tools to include in your agent's toolset If you can see the tools list after clicking Refresh, you are successfully connected to the MCP server. ## Getting Your Access Key 1. Sign up or log in at [xpoz.ai](https://xpoz.ai) 2. Navigate to your dashboard 3. Copy your access key You can also retrieve your access key programmatically using the `getUserAccessKey` tool if you are authenticated via OAuth, or check its status with `checkAccessKeyStatus`. ## Verify the Connection After setup, test the connection by asking your AI agent to run a simple query: ``` Search for Twitter user @elonmusk ``` If the agent successfully calls `getTwitterUser` and returns profile data, your connection is working. ## Next Steps See all 48 tools organized by platform. Choose between fast, paging, and CSV response modes. --- # Response Modes Source: https://docs.xpoz.ai/mcp/response-modes Paginated tools support a `responseType` parameter that controls how results are delivered. The right mode depends on whether you need quick answers, full iteration, or bulk export. ## The Three Modes Returns the first page of results immediately **without** creating a server-side pagination table. ```json { "responseType": "fast" } ``` **Behavior:** - Returns up to 100 results in a single response - No `tableName` or pagination metadata is returned - Cannot fetch additional pages -- this is a one-shot retrieval **Best for:** Quick lookups where the first batch of results is sufficient. Most AI agent queries fall into this category. Creates a server-side pagination table and returns page 1 with metadata for fetching subsequent pages. ```json { "responseType": "paging" } ``` **Response includes:** - `tableName` -- identifier for fetching additional pages - `totalPages` -- total number of available pages - `totalRows` -- total result count - `pageSize` -- items per page (100) - First page of results **Best for:** Iterating through large result sets. Use when you need comprehensive data retrieval across multiple pages. See [Pagination](/mcp/pagination) for iteration patterns. Returns an S3 download URL for bulk data export in CSV format. ```json { "responseType": "csv" } ``` **Response includes:** - S3 download URL for the CSV file - Total row count **Best for:** Bulk export for external analysis in spreadsheets, BI tools, or data pipelines. ## Comparison | | `fast` | `paging` | `csv` | |---|---|---|---| | **Speed** | Fastest | Moderate (creates table) | Moderate (generates file) | | **Max results** | 100 (first page) | Unlimited (paginated) | Unlimited (single file) | | **Pagination** | No | Yes | No | | **Output format** | JSON in response | JSON per page | CSV file on S3 | | **Token cost** | Lowest | Higher (multiple calls) | Low (URL only) | | **Best for** | Quick lookups | Full data iteration | Bulk export | ## When to Use Each Mode - You need a quick answer and the first 100 results are enough - You are doing exploratory queries to understand the data - You want the lowest latency and token consumption - The agent is answering a simple question like "What are the latest posts by @username?" - You need to analyze a complete dataset (all posts matching a query) - You are building aggregations or statistics across all results - You need more than 100 results and want to iterate programmatically - The agent is doing deep analysis like "Analyze all posts mentioning AI in the last month" - You need to export data for use outside the AI agent - You are feeding data into a spreadsheet, BI tool, or data pipeline - You want a single downloadable file with all results - The agent is fulfilling a request like "Export all posts by @username to a file" When no `responseType` is specified, the server defaults to `fast`. This is intentional -- most agent interactions only need the first page of results, and `fast` mode avoids the overhead of creating a pagination table. ## Tools That Support Response Modes Response modes are available on all paginated tools: - **Twitter:** `getTwitterPostsByAuthor`, `getTwitterPostsByKeywords`, `getTwitterPostRetweets`, `getTwitterPostQuotes`, `getTwitterPostComments`, `getTwitterPostInteractingUsers`, `getTwitterUserConnections`, `getTwitterUsersByKeywords` - **Instagram:** `getInstagramPostsByUser`, `getInstagramPostsByKeywords`, `getInstagramUserConnections`, `getInstagramPostInteractingUsers`, `getInstagramUsersByKeywords` - **Reddit:** `getRedditPostsByKeywords`, `getRedditCommentsByKeywords`, `getRedditUsersByKeywords` - **TikTok:** `getTiktokPostsByUser`, `getTiktokPostsByKeywords`, `getTiktokPostsByHashtags`, `getTiktokUsersByKeywords`, `getTiktokUsersByHashtags` ## Related - [Pagination](/mcp/pagination) -- How to iterate through pages in `paging` mode - [Field Selection](/mcp/field-selection) -- Reduce response size by selecting specific fields --- # Pagination Source: https://docs.xpoz.ai/mcp/pagination When you use `responseType: "paging"`, the Xpoz MCP server creates a server-side cached table and returns results 100 items per page. This enables efficient iteration through large datasets without re-executing the underlying query. ## How It Works ``` 1. First call (with responseType: "paging") ├── Server executes the query ├── Creates a cached pagination table ├── Returns page 1 + metadata └── tableName: "op_getTwitterPostsByKeywords_1718..." 2. Subsequent calls (with tableName + pageNumber) ├── Server looks up the cached table ├── Returns the requested page (O(1) lookup) └── No query re-execution needed ``` ## First Call Set `responseType` to `"paging"` on your initial request. The response includes pagination metadata alongside the first page of results. **Example -- search Twitter posts:** ```json { "tool": "getTwitterPostsByKeywords", "arguments": { "query": "artificial intelligence", "responseType": "paging" } } ``` **Response metadata:** | Field | Type | Description | |---|---|---| | `tableName` | string | Identifier for the cached pagination table | | `totalPages` | number | Total number of pages available | | `totalRows` | number | Total number of matching results | | `pageSize` | number | Items per page (always 100) | | `pageNumber` | number | Current page number (1 on first call) | ## Fetching Additional Pages Pass the `tableName` from the first response along with the desired `pageNumber`: ```json { "tool": "getTwitterPostsByKeywords", "arguments": { "tableName": "op_getTwitterPostsByKeywords_1718123456_abc", "pageNumber": 2 } } ``` When fetching subsequent pages, you only need `tableName` and `pageNumber`. The original query parameters are not required -- the cached table already contains the full result set. ## Iterating Through All Pages A typical pattern for retrieving all results: ``` Step 1: Call tool with responseType: "paging" → Get tableName, totalPages, page 1 data Step 2: Loop from page 2 to totalPages → Call tool with tableName + pageNumber → Process each page of results Step 3: All data retrieved ``` **Example conversation flow:** ``` Agent: I'll search for AI-related tweets and iterate through all results. Call 1: getTwitterPostsByKeywords(query: "AI", responseType: "paging") → tableName: "op_..._abc", totalPages: 5, totalRows: 487, page 1 (100 items) Call 2: getTwitterPostsByKeywords(tableName: "op_..._abc", pageNumber: 2) → page 2 (100 items) Call 3: getTwitterPostsByKeywords(tableName: "op_..._abc", pageNumber: 3) → page 3 (100 items) Call 4: getTwitterPostsByKeywords(tableName: "op_..._abc", pageNumber: 4) → page 4 (100 items) Call 5: getTwitterPostsByKeywords(tableName: "op_..._abc", pageNumber: 5) → page 5 (87 items) ``` ## Bulk Page Fetching Some tools support fetching multiple pages at once using the `pageNumberEnd` parameter: ```json { "tool": "getTwitterPostsByKeywords", "arguments": { "tableName": "op_..._abc", "pageNumber": 1, "pageNumberEnd": 5 } } ``` This returns pages 1 through 5 in a single response, reducing the number of round trips. ## Page Size All paginated tools use a fixed page size of **100 items per page**. User connection tools (`getTwitterUserConnections`, `getInstagramUserConnections`) use **1,000 users per page** with default fields. ## Table Lifecycle Cached pagination tables are temporary and managed automatically: - Tables are created when the first `paging` request is made - The server handles cleanup automatically - If a table expires or is not found, re-issue the original query with `responseType: "paging"` to create a new one Do not store `tableName` values for long-term use. They are temporary identifiers tied to a specific query execution. Always be prepared to re-query if a table is no longer available. ## Related - [Response Modes](/mcp/response-modes) -- Choosing between fast, paging, and CSV - [Field Selection](/mcp/field-selection) -- Reduce page payload size by selecting specific fields - [Operations](/mcp/operations) -- Long-running operations that produce paginated results --- # Field Selection Source: https://docs.xpoz.ai/mcp/field-selection All post, user, and comment tools support a `fields` parameter that lets you specify exactly which fields to include in the response. This dramatically improves response time and reduces token consumption. Always specify only the fields you need. Requesting all fields when you only need a few wastes tokens and slows down responses. ## Usage Pass an array of field names to the `fields` parameter: ```json { "tool": "getTwitterPostsByKeywords", "arguments": { "query": "artificial intelligence", "fields": ["id", "text", "authorUsername", "retweetCount", "createdAtDate"] } } ``` When `fields` is omitted, tools return a set of default fields (not all fields). ## Available Fields by Platform **Default fields:** `id`, `text`, `authorUsername`, `impressionCount`, `lang`, `createdAtDate` | Category | Fields | |---|---| | **IDs and Content** | `id`, `authorId`, `authorUsername`, `text` | | **Engagement** | `bookmarkCount`, `impressionCount`, `likeCount`, `quoteCount`, `replyCount`, `retweetCount` | | **References** | `conversationId`, `quotedTweetId`, `retweetedTweetId`, `replyToTweetId`, `replyToUserId`, `replyToUsername`, `originalTweetId`, `editedTweets` | | **Content Tags** | `hashtags`, `mentions`, `mediaUrls`, `urls` | | **Status** | `status`, `deleted`, `suspended`, `possiblySensitive`, `isRetweet` | | **Metadata** | `lang`, `source`, `createdAt`, `createdAtDate` | | **Birdwatch** | `hasBirdwatchNotes`, `birdwatchNotesId`, `birdwatchNotesText`, `birdwatchNotesUrl` | | **AI** | `grokGeneratedContent` | | **Location** | `country`, `region`, `city` | **Default fields:** `id`, `username`, `name` | Category | Fields | |---|---| | **Identity** | `id`, `username`, `name` | | **Profile** | `profileImageUrl`, `profileBannerUrl`, `profileInterstitialType`, `verifiedType`, `description`, `location` | | **Counts** | `followersCount`, `followingCount`, `tweetCount`, `listedCount`, `likesCount`, `mediaCount` | | **Verification** | `verified`, `isVerified`, `verifiedSinceDatetime` | | **Status** | `status`, `protected` | | **Metadata** | `source`, `modifiedAt`, `createdAt`, `pinnedTweetId` | | **Languages** | `nLang`, `nLangsFiltered` | | **Labels** | `label`, `labelType` | | **Account History** | `usernameChanges`, `lastUsernameChangeDatetime`, `accountBasedIn`, `locationAccurate` | **Default fields:** `id`, `caption`, `username`, `createdAtDate` | Category | Fields | |---|---| | **Identity** | `id`, `userId`, `postType` | | **Content** | `caption`, `mediaType`, `imageUrl`, `videoUrl`, `audioOnlyUrl` | | **Metadata** | `codeUrl`, `profilePicUrl`, `videoSubtitlesUri`, `subtitles`, `location` | | **Engagement** | `likeCount`, `commentCount`, `reshareCount`, `videoPlayCount` | | **Video** | `videoDuration` | | **Timestamps** | `createdAt`, `createdAtTimestamp`, `createdAtDate` | | **Account** | `username`, `fullName` | **Default fields:** `id`, `username`, `fullName` | Category | Fields | |---|---| | **Identity** | `id`, `username`, `fullName` | | **Profile** | `profileUrl`, `profilePicUrl`, `biography`, `externalUrl` | | **Status** | `isPrivate`, `isVerified` | | **Counts** | `followerCount`, `followingCount`, `mediaCount` | | **Metadata** | `profilePicId`, `profileInterstitialType`, `hasAnonymousProfilePicture` | **Default fields:** `id`, `text`, `username`, `createdAtDate` | Category | Fields | |---|---| | **Content** | `id`, `text` | | **References** | `parentPostId`, `parentPostUserId`, `parentCommentId`, `repliedToCommentId` | | **Metadata** | `type`, `childCommentCount`, `status` | | **Author** | `userId`, `username`, `fullName` | | **Engagement** | `likeCount` | | **Flags** | `isSpam`, `hasTranslation` | | **Timestamps** | `createdAt`, `createdAtTimestamp`, `createdAtDate` | **Default fields:** `id`, `title`, `authorUsername`, `subredditName`, `createdAtDate` | Category | Fields | |---|---| | **Content** | `id`, `title`, `selftext`, `url`, `postUrl`, `permalink` | | **Media** | `thumbnail`, `postHint`, `domain` | | **Author** | `authorId`, `authorUsername`, `subredditId`, `subredditName` | | **Engagement** | `score`, `upvotes`, `downvotes`, `upvoteRatio`, `commentsCount`, `crosspostsCount` | | **Content Type** | `isSelf`, `isVideo`, `isOriginalContent` | | **Visibility** | `over18`, `spoiler`, `locked`, `stickied`, `archived` | | **Flair** | `linkFlairText` | | **Cross-post** | `crosspostParent` | | **Timestamps** | `createdAt`, `createdAtTimestamp`, `createdAtDate` | **Default fields:** `id`, `username`, `totalKarma` | Category | Fields | |---|---| | **Identity** | `id`, `username` | | **Profile** | `profileUrl`, `profilePicUrl`, `snoovatarImg`, `profileTitle`, `profileDescription`, `profileBannerUrl` | | **Karma** | `linkKarma`, `commentKarma`, `totalKarma`, `awardeeKarma`, `awarderKarma` | | **Status** | `isGold`, `isMod`, `isEmployee`, `isSuspended`, `verified`, `isBlocked` | | **Preferences** | `hasVerifiedEmail`, `acceptFollowers`, `hasSubscribed`, `hideFromRobots`, `prefShowSnoovatar` | | **Timestamps** | `createdAt`, `createdAtTimestamp`, `createdAtDate` | **Default fields:** `id`, `body`, `authorUsername`, `createdAtDate` | Category | Fields | |---|---| | **Content** | `id`, `body` | | **References** | `parentPostId`, `parentId` | | **Author** | `authorId`, `authorUsername`, `postSubredditId`, `postSubredditName` | | **Engagement** | `score`, `upvotes`, `downvotes` | | **Structure** | `depth`, `controversiality`, `isSubmitter` | | **Status** | `stickied`, `collapsed`, `edited`, `distinguished` | | **Timestamps** | `createdAt`, `createdAtTimestamp`, `createdAtDate` | **Default fields:** `id`, `description`, `username`, `createdAtDate` | Category | Fields | |---|---| | **Content** | `id`, `postType`, `description`, `descriptionLanguage` | | **Author** | `userId`, `username`, `nickname` | | **Media** | `videoThumbnail`, `videoUrl`, `hashtags`, `duration` | | **Engagement** | `likeCount`, `commentCount`, `playCount`, `collectCount`, `downloadCount`, `forwardCount` | | **Metadata** | `isPrivate`, `transcriptsJson` | | **Timestamps** | `createdAt`, `createdAtTimestamp`, `createdAtDate` | **Default fields:** `id`, `username`, `nickname` | Category | Fields | |---|---| | **Identity** | `id`, `username`, `nickname`, `secUid` | | **Profile** | `signature`, `avatar`, `language`, `region` | | **Status** | `isPrivate`, `isVerified` | | **Counts** | `followerCount`, `followingCount`, `likeCount`, `postCount` | | **Metadata** | `usernameModifyTime`, `createdAt` | **Default fields:** `id`, `text`, `username`, `createdAtDate` | Category | Fields | |---|---| | **Content** | `id`, `postId`, `text` | | **Author** | `userId`, `username` | | **Engagement** | `likeCount` | | **Timestamps** | `createdAt`, `createdAtTimestamp`, `createdAtDate` | ## Examples by Use Case Focus on metrics and timing: ```json { "fields": ["id", "text", "retweetCount", "likeCount", "quoteCount", "replyCount", "createdAtDate"] } ``` Focus on text and author context: ```json { "fields": ["id", "text", "authorUsername", "hashtags", "mentions", "createdAtDate"] } ``` Focus on identity and reach: ```json { "fields": ["id", "username", "name", "followersCount", "followingCount", "description", "isVerified"] } ``` When you only need to count or reference results: ```json { "fields": ["id"] } ``` If you are unsure which fields you need, start with the defaults (omit the `fields` parameter). Then narrow down to specific fields once you know what your analysis requires. ## Related - [Response Modes](/mcp/response-modes) -- Control how results are delivered - [Pagination](/mcp/pagination) -- Iterate through large result sets --- # Query Syntax Source: https://docs.xpoz.ai/mcp/query-syntax Tools that accept a `query` or `keywords` parameter support a Lucene-style search syntax. This gives you precise control over what results are returned. ## Quick Reference | Syntax | Example | Meaning | |---|---|---| | Plain keywords | `bitcoin crypto` | Match either term (OR) | | Quoted phrase | `"machine learning"` | Exact phrase match | | AND | `AI AND robotics` | Both terms required | | OR | `Tesla OR SpaceX` | Either term matches | | Grouping | `(AI OR ML) AND healthcare` | Combine operators | | @handles | `@karpathy` | Match mentions | ## Plain Keywords Space-separated keywords are treated as OR queries -- results matching **any** of the terms are returned. ``` artificial intelligence ``` This matches posts containing "artificial" OR "intelligence" (or both). ## Quoted Phrases Wrap terms in double quotes to match an exact phrase: ``` "machine learning" ``` This only matches posts containing the exact phrase "machine learning" as a contiguous string. You can combine phrases with other terms: ``` "deep learning" AND python ``` ## Boolean Operators Two boolean operators are supported: `AND` and `OR`. They are case-insensitive. Both terms must be present in the result. ``` AI AND crypto ``` ``` "artificial intelligence" AND ethics ``` Either term (or both) can be present. This is the default behavior for space-separated words. ``` bitcoin OR ethereum ``` ``` "climate change" OR "global warming" ``` ## Grouping with Parentheses Use parentheses to control operator precedence: ``` (AI OR "artificial intelligence") AND ethics ``` ``` (bitcoin OR ethereum) AND (regulation OR policy) ``` Without parentheses, operators are evaluated left to right. Use grouping to make your intent explicit, especially when mixing AND and OR. ## Platform-Specific Search Scope Different tools search different fields depending on the platform: | Platform | Content Searched | |---|---| | **Twitter posts** | Post text | | **Instagram posts** | Captions and subtitles | | **Instagram comments** | Comment text | | **Reddit posts** | Title and selftext | | **Reddit comments** | Body text | | **TikTok posts** | Description and transcripts | ## Examples by Platform **Find posts about AI from specific conversations:** ``` "artificial intelligence" AND (startup OR venture) ``` **Find posts mentioning a user:** ``` @elonmusk AND Tesla ``` **Find fashion-related posts:** ``` "street style" OR "fashion week" ``` **Find food content in a specific cuisine:** ``` (sushi OR ramen) AND Tokyo ``` **Find technical discussions:** ``` "rust programming" AND (async OR concurrency) ``` **Find product reviews:** ``` review AND (iPhone OR Pixel) ``` **Find trending content:** ``` "day in my life" AND (NYC OR "New York") ``` **Find educational content:** ``` (tutorial OR "how to") AND cooking ``` For TikTok, also consider using `getTiktokPostsByHashtags` which searches the indexed hashtags column directly -- this is faster and more precise than keyword search for hashtag-based discovery. ## Syntax Rules These rules are enforced by the server. Queries that violate them will be rejected. | Rule | Valid | Invalid | |---|---|---| | Operators need terms on both sides | `AI AND crypto` | `AND crypto` | | Cannot start with AND or OR | `bitcoin OR ethereum` | `OR bitcoin` | | Cannot end with an operator | `AI AND ML` | `AI AND` | | Max query length: 250 characters | -- | -- | ## Unsupported Syntax The following are **not supported** and will be stripped or treated as spaces: | Syntax | Behavior | |---|---| | Field operators (`from:`, `lang:`, `since:`, `until:`) | Stripped from query | | Forward slashes (`/`) | Treated as spaces (`24/7` becomes `24 7`) | | Colons (`:`) | Treated as spaces | | Backslashes (`\`) | Removed | | Apostrophes (`'`) | Removed | | Square brackets (`[]`) | Removed | | Leading wildcards (`*term`) | Stripped | If you need to filter by date range, language, or author, use the dedicated tool parameters (e.g., `startDate`, `endDate`, `language`, `username`) instead of embedding them in the query string. ## Related - [Field Selection](/mcp/field-selection) -- Control which fields are returned in results - [Response Modes](/mcp/response-modes) -- Choose how results are delivered --- # Operations Source: https://docs.xpoz.ai/mcp/operations Some queries -- especially large pagination or CSV export jobs -- run as background operations. The Xpoz MCP server provides two tools for managing these: `checkOperationStatus` and `cancelOperation`. ## How Operations Work When a tool triggers a long-running task, it returns an operation ID instead of immediate results. Your agent then polls for completion using `checkOperationStatus`. ``` 1. Agent calls a tool (e.g., large paging query) └── Server returns: operationId, status: "running" 2. Agent polls checkOperationStatus(operationId) └── Server returns: status: "running" 3. Agent polls again └── Server returns: status: "completed", results: [...] ``` Most AI agents handle this polling automatically. You typically don't need to manage operations manually — just call a tool and your agent retrieves the results when ready. ## Operation States | State | Description | |---|---| | `running` | Operation is actively executing | | `completed` | Successfully finished — results are available | | `failed` | An error occurred during execution | | `cancelled` | Gracefully stopped by a `cancelOperation` call | ## checkOperationStatus Polls the status of an async operation and retrieves results when complete. | Parameter | Type | Required | Description | |---|---|---|---| | `operationId` | string | Yes | The operation ID returned by the initiating tool call | **What it returns by state:** Returns the operation results: - **For query operations:** Paginated results with data - **For CSV export operations:** An S3 download URL ```json { "status": "completed", "message": "Operation completed successfully. Processed 487 items.", "results": [...] } ``` Returns the current status with elapsed time: ```json { "status": "running", "message": "Processing... 250 processed", "duration": 12 } ``` Returns the error details: ```json { "status": "failed", "message": "Operation failed: Connection timeout" } ``` ## cancelOperation Gracefully stops a running operation. | Parameter | Type | Required | Description | |---|---|---|---| | `operationId` | string | Yes | The operation ID to cancel | Only works on operations with `running` status. The operation stops at its next processing checkpoint. If you receive an error that an operation was not found, it may have expired. Re-issue the original query to start a new operation. ## Related - [Response Modes](/mcp/response-modes) — CSV mode triggers async operations for large exports - [Pagination](/mcp/pagination) — Paging mode may trigger operations for large result sets --- # Tools Overview Source: https://docs.xpoz.ai/mcp/tools/overview The Xpoz MCP server exposes **48 tools** across four social media platforms plus tracking and account management. Each tool is read-only and safe to call without side effects (except tracking tools, which modify your tracked items list). ## Twitter/X (13 tools) | Tool | Description | Pagination | |------|-------------|------------| | [`getTwitterUser`](/mcp/tools/twitter#getTwitterUser) | Get user profile by ID or username | No | | [`getTwitterUsers`](/mcp/tools/twitter#getTwitterUsers) | Get 1-100 user profiles by IDs or usernames | No | | [`searchTwitterUsers`](/mcp/tools/twitter#searchTwitterUsers) | Search users by name/username (max 10) | No | | [`getTwitterUserConnections`](/mcp/tools/twitter#getTwitterUserConnections) | Get followers or following | Yes | | [`getTwitterUsersByKeywords`](/mcp/tools/twitter#getTwitterUsersByKeywords) | Find users who posted about keywords | Yes | | [`getTwitterPostsByIds`](/mcp/tools/twitter#getTwitterPostsByIds) | Get 1-100 posts by numeric IDs | No | | [`getTwitterPostsByAuthor`](/mcp/tools/twitter#getTwitterPostsByAuthor) | Get posts by author username | Yes | | [`getTwitterPostsByKeywords`](/mcp/tools/twitter#getTwitterPostsByKeywords) | Search posts by keywords | Yes | | [`getTwitterPostRetweets`](/mcp/tools/twitter#getTwitterPostRetweets) | Get retweets of a specific post | Yes | | [`getTwitterPostQuotes`](/mcp/tools/twitter#getTwitterPostQuotes) | Get quote posts of a specific post | Yes | | [`getTwitterPostComments`](/mcp/tools/twitter#getTwitterPostComments) | Get replies to a specific post | Yes | | [`getTwitterPostInteractingUsers`](/mcp/tools/twitter#getTwitterPostInteractingUsers) | Get users who interacted with a post | Yes | | [`countTweets`](/mcp/tools/twitter#countTweets) | Count tweets matching a phrase in a date range | No | ## Instagram (9 tools) | Tool | Description | Pagination | |------|-------------|------------| | [`getInstagramUser`](/mcp/tools/instagram#getInstagramUser) | Get user profile by ID or username | No | | [`searchInstagramUsers`](/mcp/tools/instagram#searchInstagramUsers) | Search users by name/username (max 10) | No | | [`getInstagramUserConnections`](/mcp/tools/instagram#getInstagramUserConnections) | Get followers or following | Yes | | [`getInstagramPostInteractingUsers`](/mcp/tools/instagram#getInstagramPostInteractingUsers) | Get users who liked/commented on a post | Yes | | [`getInstagramUsersByKeywords`](/mcp/tools/instagram#getInstagramUsersByKeywords) | Find users who posted about keywords | Yes | | [`getInstagramPostsByIds`](/mcp/tools/instagram#getInstagramPostsByIds) | Get 1-100 posts by strong IDs | No | | [`getInstagramPostsByUser`](/mcp/tools/instagram#getInstagramPostsByUser) | Get posts by user ID or username | Yes | | [`getInstagramPostsByKeywords`](/mcp/tools/instagram#getInstagramPostsByKeywords) | Search posts by keywords | Yes | | [`getInstagramCommentsByPostId`](/mcp/tools/instagram#getInstagramCommentsByPostId) | Get comments for a post | Yes | ## Reddit (9 tools) | Tool | Description | Pagination | |------|-------------|------------| | [`getRedditUser`](/mcp/tools/reddit#getRedditUser) | Get user profile by username | No | | [`searchRedditUsers`](/mcp/tools/reddit#searchRedditUsers) | Search users by name/username (max 50) | No | | [`getRedditUsersByKeywords`](/mcp/tools/reddit#getRedditUsersByKeywords) | Find users who posted about keywords | Yes | | [`getRedditPostsByKeywords`](/mcp/tools/reddit#getRedditPostsByKeywords) | Search posts by keywords | Yes | | [`getRedditPostWithCommentsById`](/mcp/tools/reddit#getRedditPostWithCommentsById) | Get a post with its comments | Yes | | [`getRedditCommentsByKeywords`](/mcp/tools/reddit#getRedditCommentsByKeywords) | Search comments by keywords | Yes | | [`searchRedditSubreddits`](/mcp/tools/reddit#searchRedditSubreddits) | Search subreddits by name (max 50) | No | | [`getRedditSubredditWithPostsByName`](/mcp/tools/reddit#getRedditSubredditWithPostsByName) | Get subreddit with its posts | Yes | | [`getRedditSubredditsByKeywords`](/mcp/tools/reddit#getRedditSubredditsByKeywords) | Find subreddits where keywords appear | Yes | ## TikTok (10 tools) | Tool | Description | Pagination | |------|-------------|------------| | [`getTiktokUser`](/mcp/tools/tiktok#getTiktokUser) | Get user profile by ID or username | No | | [`searchTiktokUsers`](/mcp/tools/tiktok#searchTiktokUsers) | Search users by name/username (max 10) | No | | [`getTiktokUsersByKeywords`](/mcp/tools/tiktok#getTiktokUsersByKeywords) | Find users who posted about keywords | Yes | | [`getTiktokUsersByHashtags`](/mcp/tools/tiktok#getTiktokUsersByHashtags) | Find users who posted with specific hashtags | Yes | | [`getTiktokPostsByIds`](/mcp/tools/tiktok#getTiktokPostsByIds) | Get 1-100 posts by numeric IDs | No | | [`getTiktokPostsByUser`](/mcp/tools/tiktok#getTiktokPostsByUser) | Get posts by user ID or username | Yes | | [`getTiktokPostsByKeywords`](/mcp/tools/tiktok#getTiktokPostsByKeywords) | Search posts by keywords | Yes | | [`getTiktokPostsByHashtags`](/mcp/tools/tiktok#getTiktokPostsByHashtags) | Search posts by hashtags | Yes | | [`getTiktokCommentsByPostId`](/mcp/tools/tiktok#getTiktokCommentsByPostId) | Get comments for a post | Yes | TikTok is the only platform with hashtag-specific tools (`getTiktokUsersByHashtags` and `getTiktokPostsByHashtags`). These search the indexed `hashtags` column directly for precise matching. ## Tracking (3 tools) | Tool | Description | Pagination | |------|-------------|------------| | [`getTrackedItems`](/mcp/tools/tracking#getTrackedItems) | List all tracked keywords, users, subreddits, and hashtags | No | | [`addTrackedItems`](/mcp/tools/tracking#addTrackedItems) | Add items to track across platforms | No | | [`removeTrackedItems`](/mcp/tools/tracking#removeTrackedItems) | Remove tracked items | No | ## Account & Auth (3 tools) | Tool | Description | Pagination | |------|-------------|------------| | [`getAccountDetails`](/mcp/tools/account#getAccountDetails) | Get plan, billing, and usage info | No | | [`getUserAccessKey`](/mcp/tools/account#getUserAccessKey) | Retrieve your access key | No | | [`checkAccessKeyStatus`](/mcp/tools/account#checkAccessKeyStatus) | Check access key status without revealing the key | No | ## Operations (2 tools) | Tool | Description | Pagination | |------|-------------|------------| | `checkOperationStatus` | Check status and retrieve results from a background operation | No | | `cancelOperation` | Cancel a running background operation | No | For details on how operations work with paginated tools, see [Operations](/mcp/operations). --- # Twitter/X Tools Source: https://docs.xpoz.ai/mcp/tools/twitter Xpoz provides **13 Twitter/X tools** across two categories: user tools and post tools. ## Available Fields ### User Fields These fields are available on all user tools (`getTwitterUser`, `getTwitterUsers`, `searchTwitterUsers`, `getTwitterUserConnections`, `getTwitterUsersByKeywords`, `getTwitterPostInteractingUsers`). **Default:** `id`, `username`, `name` | Category | Fields | |----------|--------| | **Identity** | `id`, `username`, `name`, `description`, `location`, `profileImageUrl`, `profileBannerUrl` | | **Verification** | `verified`, `isVerified`, `verifiedType`, `verifiedSinceDatetime` | | **Metrics** | `followersCount`, `followingCount`, `tweetCount`, `listedCount`, `likesCount`, `mediaCount` | | **Metadata** | `pinnedTweetId`, `source`, `label`, `labelType`, `accountBasedIn`, `locationAccurate` | | **History** | `usernameChanges`, `lastUsernameChangeDatetime`, `createdAt` | `getTwitterUsersByKeywords` also returns aggregation fields: `aggRelevance`, `relevantTweetsCount`, `relevantTweetsImpressionsSum`, `relevantTweetsLikesSum`, `relevantTweetsQuotesSum`, `relevantTweetsRepliesSum`, `relevantTweetsRetweetsSum`. ### Post Fields These fields are available on all post tools (`getTwitterPostsByIds`, `getTwitterPostsByAuthor`, `getTwitterPostsByKeywords`, `getTwitterPostRetweets`, `getTwitterPostQuotes`, `getTwitterPostComments`). **Default:** `id`, `text`, `authorUsername`, `createdAtDate` | Category | Fields | |----------|--------| | **Core** | `id`, `text`, `authorId`, `authorUsername`, `createdAt`, `createdAtDate` | | **Engagement** | `retweetCount`, `replyCount`, `likeCount`, `quoteCount`, `impressionCount`, `bookmarkCount` | | **Metadata** | `lang`, `possiblySensitive`, `suspended`, `deleted`, `source`, `isRetweet`, `hasBirdwatchNotes`, `status` | | **Birdwatch** | `birdwatchNotesId`, `birdwatchNotesText`, `birdwatchNotesUrl` | | **Relations** | `conversationId`, `quotedTweetId`, `retweetedTweetId`, `replyToTweetId`, `replyToUserId`, `replyToUsername`, `originalTweetId`, `editedTweets` | | **Content** | `hashtags`, `mentions`, `mediaUrls`, `urls`, `grokGeneratedContent` | | **Location** | `country`, `region`, `city` | Always specify only the fields you need using the `fields` parameter. For example, `["id", "text", "retweetCount", "likeCount", "createdAtDate"]` for engagement analysis. See [Field Selection](/mcp/field-selection) for details. ### getTwitterUsers Get one or more Twitter user profiles by IDs or usernames (1-100 per request). | Parameter | Type | Required | Description | |-----------|------|----------|-------------| | `identifiers` | string[] | Yes | Array of user IDs or usernames (1-100). All must match `identifierType`. | | `identifierType` | string | Yes | `"id"` or `"username"`. | | `fields` | string[] | No | Fields to return. | | `forceLatest` | boolean | No | Force fresh data from API. Default: `false`. | Returns only found users, omitting not-found identifiers. Batching multiple users in a single `getTwitterUsers` call is more efficient than calling `getTwitterUser` multiple times. ### getTwitterUserConnections Get followers or following for a Twitter user. | Parameter | Type | Required | Description | |-----------|------|----------|-------------| | `username` | string | Yes | Twitter username (without `@`). | | `connectionType` | string | Yes | `"followers"` or `"following"`. | | `responseType` | string | No | `"fast"` (default), `"paging"`, or `"csv"`. See [Response Modes](/mcp/response-modes). | | `limit` | number | No | Max results. Fast: capped at 300. Paging/CSV: max 500,000. | | `fields` | string[] | No | User fields to return. | | `pageNumber` | integer | No | Page to fetch (1-indexed). Requires `tableName` for pages > 1. | | `pageNumberEnd` | integer | No | End page for bulk fetching. Must be >= `pageNumber`. | | `tableName` | string | No | Cached table name from a previous pagination response. | | `forceLatest` | boolean | No | Force fresh data from API. Default: `false`. | Supports server-side pagination with 1,000 users per page (with default fields) or 100 per page (with extra fields). See [Pagination](/mcp/pagination) for details. ## Post Tools ### getTwitterPostsByIds Get one or more Twitter posts by numeric IDs (1-100 per request). | Parameter | Type | Required | Description | |-----------|------|----------|-------------| | `postIds` | string[] | Yes | Array of numeric post IDs (1-100). Each must be digits only. | | `fields` | string[] | No | Fields to return. | | `forceLatest` | boolean | No | Force fresh data from API. Default: `false`. | Returns only found posts, omitting not-found IDs. Returns the most up-to-date data available. ### getTwitterPostsByKeywords Search Twitter posts by keywords. | Parameter | Type | Required | Description | |-----------|------|----------|-------------| | `query` | string | Yes | Full-text search of post content. Max 250 characters. Supports exact phrases, boolean operators (`AND`, `OR`), and parentheses. Do not use `from:`, `lang:`, or other filter operators in the query -- use dedicated parameters. | | `responseType` | string | No | `"fast"` (default), `"paging"`, or `"csv"`. See [Response Modes](/mcp/response-modes). | | `limit` | number | No | Max results. Fast: capped at 300. Paging/CSV: max 500,000. | | `authorUsername` | string | No | Filter posts by author username. | | `authorId` | string | No | Filter posts by author ID (numeric). Alternative to `authorUsername`. | | `language` | string | No | Filter by language. | | `filterOutRetweets` | boolean | No | Exclude retweets from results. Default: `false`. | | `startDate` | string | No | Start date filter (`YYYY-MM-DD`). | | `endDate` | string | No | End date filter (`YYYY-MM-DD`). | | `fields` | string[] | No | Fields to return. | | `pageNumber` | integer | No | Page to fetch (1-indexed). | | `pageNumberEnd` | integer | No | End page for bulk fetching. | | `tableName` | string | No | Cached table name from a previous pagination response. | | `forceLatest` | boolean | No | Force fresh data from API. Default: `false`. | Supports server-side pagination with 100 posts per page. See [Query Syntax](/mcp/query-syntax) for details on search operators. ### getTwitterPostQuotes Get quote posts of a specific post. | Parameter | Type | Required | Description | |-----------|------|----------|-------------| | `postId` | string | Yes | Numeric post ID (digits only). | | `responseType` | string | No | `"fast"` (default), `"paging"`, or `"csv"`. See [Response Modes](/mcp/response-modes). | | `limit` | number | No | Max results. Fast: capped at 300. Paging/CSV: max 500,000. | | `startDate` | string | No | Start date filter (`YYYY-MM-DD`). | | `fields` | string[] | No | Post fields to return. | | `pageNumber` | integer | No | Page to fetch (1-indexed). | | `pageNumberEnd` | integer | No | End page for bulk fetching. | | `tableName` | string | No | Cached table name from a previous pagination response. | | `forceLatest` | boolean | No | Force fresh data from API. Default: `false`. | Data older than 10 days is automatically refreshed. Supports server-side pagination with 100 posts per page. ### getTwitterPostInteractingUsers Get user profiles of people who interacted with a specific post. | Parameter | Type | Required | Description | |-----------|------|----------|-------------| | `postId` | string | Yes | Numeric post ID (digits only). | | `interactionType` | string | Yes | `"commenters"`, `"quoters"`, or `"retweeters"`. | | `responseType` | string | No | `"fast"` (default), `"paging"`, or `"csv"`. See [Response Modes](/mcp/response-modes). | | `limit` | number | No | Max results. Fast: capped at 300. Paging/CSV: max 500,000. | | `startDate` | string | No | Start date filter (`YYYY-MM-DD`). | | `endDate` | string | No | End date filter (`YYYY-MM-DD`). | | `fields` | string[] | No | **User** fields to return (not post fields). | | `pageNumber` | integer | No | Page to fetch (1-indexed). | | `pageNumberEnd` | integer | No | End page for bulk fetching. | | `tableName` | string | No | Cached table name from a previous pagination response. | | `forceLatest` | boolean | No | Force fresh data from API. Default: `false`. | This tool returns **user profiles**, not post data. The `fields` parameter accepts user fields (see [User Fields](#user-fields) above). Supports server-side pagination with 1,000 users per page (with default fields) or 100 per page (with extra fields). --- # Instagram Tools Source: https://docs.xpoz.ai/mcp/tools/instagram Xpoz provides **9 Instagram tools** across three categories: users, posts, and comments. ## Available Fields ### User Fields These fields are available on all user tools (`getInstagramUser`, `searchInstagramUsers`, `getInstagramUserConnections`, `getInstagramPostInteractingUsers`, `getInstagramUsersByKeywords`). **Default:** `id`, `username`, `fullName` | Category | Fields | |----------|--------| | **Identity** | `id`, `username`, `fullName`, `biography`, `profilePicUrl`, `profilePicId`, `profileUrl`, `externalUrl` | | **Status** | `isPrivate`, `isVerified`, `hasAnonymousProfilePicture` | | **Metrics** | `followerCount`, `followingCount`, `mediaCount` | `getInstagramUsersByKeywords` also returns aggregation fields: `aggRelevance`, `relevantPostsCount`, `relevantPostsLikesSum`, `relevantPostsCommentsSum`, `relevantPostsResharesSum`, `relevantPostsVideoPlaysSum`. ### Post Fields These fields are available on all post tools (`getInstagramPostsByIds`, `getInstagramPostsByUser`, `getInstagramPostsByKeywords`). **Default:** `id`, `caption`, `username`, `createdAtDate` | Category | Fields | |----------|--------| | **Core** | `id`, `postType`, `userId`, `username`, `fullName`, `caption`, `createdAt`, `createdAtTimestamp`, `createdAtDate` | | **Engagement** | `likeCount`, `commentCount`, `reshareCount`, `videoPlayCount` | | **Media** | `mediaType`, `codeUrl`, `imageUrl`, `videoUrl`, `audioOnlyUrl`, `profilePicUrl`, `videoSubtitlesUri`, `subtitles`, `videoDuration` | ### Comment Fields These fields are available on `getInstagramCommentsByPostId`. **Default:** `id`, `text`, `username`, `createdAtDate` | Category | Fields | |----------|--------| | **Core** | `id`, `text`, `parentPostId`, `type`, `parentCommentId`, `repliedToCommentId`, `childCommentCount`, `userId`, `username`, `fullName`, `createdAt`, `createdAtTimestamp`, `createdAtDate` | | **Engagement** | `likeCount` | | **Status** | `status`, `isSpam`, `hasTranslation` | Always specify only the fields you need using the `fields` parameter. See [Field Selection](/mcp/field-selection) for details. ### searchInstagramUsers Search users by name, partial username, or fuzzy match with real-time results. | Parameter | Type | Required | Description | |-----------|------|----------|-------------| | `name` | string | Yes | Search query (person name, partial username, or keywords). | | `limit` | number | No | Max results. Default: `10`, max: `10`. | | `fields` | string[] | No | Fields to return. | This tool performs a real-time search. For exact username lookups, use `getInstagramUser` instead. ### getInstagramPostInteractingUsers Get user profiles of people who interacted with an Instagram post (commenters or likers). | Parameter | Type | Required | Description | |-----------|------|----------|-------------| | `postId` | string | Yes | Post ID in strong_id format (e.g., `"3606450040306139062_4836333238"`). | | `interactionType` | string | Yes | `"commenters"` or `"likers"`. | | `responseType` | string | No | `"fast"` (default) or `"paging"`. CSV is not supported. | | `limit` | number | No | Max results. Fast: capped at 300. Paging: max 500,000. | | `fields` | string[] | No | **User** fields to return (see [User Fields](#user-fields) above). | | `pageNumber` | integer | No | Page to fetch (1-indexed). | | `pageNumberEnd` | integer | No | End page for bulk fetching. | | `tableName` | string | No | Cached table name from a previous pagination response. | | `forceLatest` | boolean | No | Force fresh data from API. Default: `false`. | This tool returns **user profiles**, not comment content. To read actual comment text, use `getInstagramCommentsByPostId` instead. The `postId` must be in strong_id format (`mediaId_userId`). Use the full `id` value returned by other Instagram tools. ## Post Tools ### getInstagramPostsByIds Get one or more Instagram posts by IDs (1-100 per request). | Parameter | Type | Required | Description | |-----------|------|----------|-------------| | `postIds` | string[] | Yes | Array of post IDs in strong_id format (1-100). E.g., `["3606450040306139062_4836333238"]`. | | `fields` | string[] | No | Fields to return. | | `forceLatest` | boolean | No | Force fresh data from API. Default: `false`. | Returns only found posts, omitting not-found IDs. Returns the most up-to-date data available. Data older than 3 days is automatically refreshed. Post IDs must be in strong_id format (`mediaId_userId`). Use the full `id` value returned by other Instagram tools. ### getInstagramPostsByKeywords Search Instagram posts by keywords in captions and video subtitles. | Parameter | Type | Required | Description | |-----------|------|----------|-------------| | `query` | string | Yes | Full-text search of post captions and subtitles. Max 250 characters. Supports exact phrases, boolean operators (`AND`, `OR`), and parentheses. | | `responseType` | string | No | `"fast"` (default), `"paging"`, or `"csv"`. See [Response Modes](/mcp/response-modes). | | `limit` | number | No | Max results. Fast: capped at 300. Paging/CSV: max 500,000. | | `startDate` | string | No | Start date filter (`YYYY-MM-DD`). | | `endDate` | string | No | End date filter (`YYYY-MM-DD`). | | `fields` | string[] | No | Fields to return. | | `pageNumber` | integer | No | Page to fetch (1-indexed). | | `pageNumberEnd` | integer | No | End page for bulk fetching. | | `tableName` | string | No | Cached table name from a previous pagination response. | | `forceLatest` | boolean | No | Force fresh data from API. Default: `false`. | Data older than 1 week is automatically refreshed. Supports server-side pagination with 100 posts per page. See [Query Syntax](/mcp/query-syntax) for details on search operators. --- # Reddit Tools Source: https://docs.xpoz.ai/mcp/tools/reddit Xpoz provides **9 Reddit tools** across four categories: users, posts, comments, and subreddits. ## Available Fields ### User Fields These fields are available on user tools (`getRedditUser`, `searchRedditUsers`, `getRedditUsersByKeywords`). **Default:** `id`, `username`, `totalKarma` | Category | Fields | |----------|--------| | **Identity** | `id`, `username`, `profileUrl`, `profilePicUrl`, `snoovatarImg`, `profileDescription`, `profileBannerUrl`, `profileTitle` | | **Karma** | `linkKarma`, `commentKarma`, `totalKarma`, `awardeeKarma`, `awarderKarma` | | **Status** | `isGold`, `isMod`, `isEmployee`, `hasVerifiedEmail`, `isSuspended`, `verified`, `isBlocked`, `acceptFollowers`, `hasSubscribed` | | **Settings** | `hideFromRobots`, `prefShowSnoovatar` | | **Timestamps** | `createdAt`, `createdAtTimestamp`, `createdAtDate` | `getRedditUsersByKeywords` also returns aggregation fields: `aggRelevance`, `relevantPostsCount`, `relevantPostsUpvotesSum`, `relevantPostsCommentsCountSum`. ### Post Fields These fields are available on post tools (`getRedditPostsByKeywords`, `getRedditPostWithCommentsById`). **Default:** `id`, `title`, `authorUsername`, `subredditName`, `createdAtDate` | Category | Fields | |----------|--------| | **Core** | `id`, `title`, `selftext`, `url`, `permalink`, `postUrl`, `thumbnail` | | **Author** | `authorId`, `authorUsername` | | **Subreddit** | `subredditName`, `subredditId` | | **Engagement** | `score`, `upvotes`, `downvotes`, `upvoteRatio`, `commentsCount`, `crosspostsCount` | | **Flags** | `isSelf`, `isVideo`, `isOriginalContent`, `over18`, `spoiler`, `locked`, `stickied`, `archived` | | **Meta** | `linkFlairText`, `postHint`, `domain`, `crosspostParent` | | **Timestamps** | `createdAt`, `createdAtTimestamp`, `createdAtDate` | ### Comment Fields These fields are available on `getRedditCommentsByKeywords` and `getRedditPostWithCommentsById`. **Default:** `id`, `body`, `authorUsername`, `createdAtDate` | Category | Fields | |----------|--------| | **Core** | `id`, `body`, `parentPostId`, `parentId` | | **Author** | `authorId`, `authorUsername` | | **Subreddit** | `postSubredditName`, `postSubredditId` | | **Engagement** | `score`, `upvotes`, `downvotes`, `controversiality` | | **Meta** | `depth`, `isSubmitter`, `stickied`, `collapsed`, `edited`, `distinguished` | | **Timestamps** | `createdAt`, `createdAtTimestamp`, `createdAtDate` | ### Subreddit Fields These fields are available on subreddit tools (`searchRedditSubreddits`, `getRedditSubredditWithPostsByName`, `getRedditSubredditsByKeywords`). **Default:** `id`, `displayName`, `title`, `subscribersCount` | Category | Fields | |----------|--------| | **Core** | `id`, `displayName`, `title`, `publicDescription`, `description` | | **Stats** | `subscribersCount`, `activeUserCount` | | **Meta** | `subredditType`, `over18`, `lang`, `url`, `subredditUrl` | | **Images** | `iconImg`, `bannerImg`, `headerImg`, `communityIcon` | | **Timestamps** | `createdAt`, `createdAtTimestamp`, `createdAtDate` | `getRedditSubredditsByKeywords` also returns aggregation fields: `aggRelevance`, `relevantPostsCount`, `relevantPostsUpvotesSum`, `relevantPostsCommentsCountSum`. Always specify only the fields you need using the `fields` parameter. See [Field Selection](/mcp/field-selection) for details. ### searchRedditUsers Search Reddit users by name, username, or profile description with real-time results. | Parameter | Type | Required | Description | |-----------|------|----------|-------------| | `query` | string | Yes | Search query (name, username, or keywords from profile). Max 250 characters. | | `limit` | integer | No | Max results. Default: `50`, max: `50`. | | `fields` | string[] | No | Fields to return. | This tool performs a real-time search. For exact username lookups, use `getRedditUser` instead. ## Post Tools ### getRedditPostsByKeywords Search Reddit posts by keywords in titles and selftext. | Parameter | Type | Required | Description | |-----------|------|----------|-------------| | `query` | string | Yes | Full-text search of post content. Max 250 characters. Supports exact phrases, boolean operators, and parentheses. | | `responseType` | string | No | `"fast"` (default), `"paging"`, or `"csv"`. See [Response Modes](/mcp/response-modes). | | `limit` | number | No | Max results. Fast: capped at 300. Paging/CSV: max 500,000. | | `sort` | string | No | Sort order: `"relevance"` (default), `"hot"`, `"top"`, `"new"`, `"comments"`. | | `time` | string | No | Time filter: `"hour"`, `"day"`, `"week"`, `"month"`, `"year"`, `"all"` (default). | | `subreddit` | string | No | Filter to a specific subreddit (without `r/` prefix). | | `startDate` | string | No | Start date filter (`YYYY-MM-DD`). | | `endDate` | string | No | End date filter (`YYYY-MM-DD`). | | `fields` | string[] | No | Fields to return. | | `pageNumber` | integer | No | Page to fetch (1-indexed). | | `pageNumberEnd` | integer | No | End page for bulk fetching. | | `tableName` | string | No | Cached table name from a previous pagination response. | | `forceLatest` | boolean | No | Force fresh data from API. Default: `false`. | Supports server-side pagination with 100 posts per page. See [Pagination](/mcp/pagination) and [Query Syntax](/mcp/query-syntax) for details. ## Comment Tools ### getRedditCommentsByKeywords Search Reddit comments by keywords in comment body text. Database-only -- searches existing records. | Parameter | Type | Required | Description | |-----------|------|----------|-------------| | `query` | string | Yes | Full-text search of comment body. Max 250 characters. Supports exact phrases, boolean operators, and parentheses. | | `responseType` | string | No | `"fast"` (default), `"paging"`, or `"csv"`. See [Response Modes](/mcp/response-modes). | | `limit` | number | No | Max results. Fast: capped at 300. Paging/CSV: max 500,000. | | `subreddit` | string | No | Filter to a specific subreddit (without `r/` prefix). | | `startDate` | string | No | Start date filter (`YYYY-MM-DD`). | | `endDate` | string | No | End date filter (`YYYY-MM-DD`). | | `fields` | string[] | No | Fields to return. | | `pageNumber` | integer | No | Page to fetch (1-indexed). | | `pageNumberEnd` | integer | No | End page for bulk fetching. | | `tableName` | string | No | Cached table name from a previous pagination response. | Supports server-side pagination with 100 comments per page. ### getRedditSubredditWithPostsByName Get subreddit details with its posts. | Parameter | Type | Required | Description | |-----------|------|----------|-------------| | `subredditName` | string | Yes | Subreddit name (without `r/` prefix). Example: `"wallstreetbets"`. | | `responseType` | string | No | `"fast"` (default) or `"paging"`. CSV is not supported. | | `limit` | number | No | Max posts to return. Fast: up to 300. Paging: max 500,000. | | `subredditFields` | string[] | No | Fields for the subreddit. See [Subreddit Fields](#subreddit-fields) above. | | `postFields` | string[] | No | Fields for the posts. See [Post Fields](#post-fields) above. | | `pageNumber` | integer | No | Page to fetch (1-indexed). | | `pageNumberEnd` | integer | No | End page for bulk fetching. | | `tableName` | string | No | Cached table name from a previous pagination response. | | `forceLatest` | boolean | No | Force fresh data from API. Default: `false`. | This tool uses separate `subredditFields` and `postFields` parameters instead of a single `fields` parameter. --- # TikTok Tools Source: https://docs.xpoz.ai/mcp/tools/tiktok Xpoz provides **10 TikTok tools** across three categories: users, posts, and comments. TikTok is unique in having hashtag-specific search tools. ## Available Fields ### User Fields These fields are available on all user tools (`getTiktokUser`, `searchTiktokUsers`, `getTiktokUsersByKeywords`, `getTiktokUsersByHashtags`). **Default:** `id`, `username`, `nickname` | Category | Fields | |----------|--------| | **Identity** | `id`, `username`, `nickname`, `signature`, `secUid`, `avatar` | | **Status** | `isPrivate`, `isVerified` | | **Metrics** | `followerCount`, `followingCount`, `likeCount`, `postCount` | | **Locale** | `language`, `region` | | **Timestamps** | `createdAt`, `usernameModifyTime` | `getTiktokUsersByKeywords` and `getTiktokUsersByHashtags` also return aggregation fields: `aggRelevance`, `relevantPostsCount`, `relevantPostsLikesSum`, `relevantPostsCommentsSum`, `relevantPostsPlaysSum`, `relevantPostsForwardsSum`. ### Post Fields These fields are available on all post tools (`getTiktokPostsByIds`, `getTiktokPostsByUser`, `getTiktokPostsByKeywords`, `getTiktokPostsByHashtags`). **Default:** `id`, `description`, `username`, `createdAtDate` | Category | Fields | |----------|--------| | **Core** | `id`, `postType`, `isPrivate`, `userId`, `username`, `nickname`, `description`, `descriptionLanguage`, `createdAt`, `createdAtTimestamp`, `createdAtDate` | | **Engagement** | `collectCount`, `commentCount`, `likeCount`, `downloadCount`, `forwardCount`, `playCount` | | **Media** | `videoThumbnail`, `videoUrl` (array of video URLs), `duration` (video length in seconds) | | **Content** | `hashtags` (array of hashtag strings), `transcriptsJson` | ### Comment Fields These fields are available on `getTiktokCommentsByPostId`. **Default:** `id`, `text`, `username`, `createdAtDate` | Category | Fields | |----------|--------| | **All** | `id`, `postId`, `userId`, `username`, `text`, `likeCount`, `createdAt`, `createdAtTimestamp`, `createdAtDate` | Always specify only the fields you need using the `fields` parameter. For example, `["id", "description", "playCount", "likeCount", "hashtags"]` for content analysis. See [Field Selection](/mcp/field-selection) for details. ### searchTiktokUsers Search TikTok users by name or username with real-time results. | Parameter | Type | Required | Description | |-----------|------|----------|-------------| | `name` | string | Yes | Search query (name, partial username, or keywords). | | `limit` | number | No | Max results. Default: `10`, max: `10`. | | `fields` | string[] | No | Fields to return. | This tool performs a real-time search. For exact username lookups, use `getTiktokUser` instead. ### getTiktokUsersByHashtags Search for users who posted content tagged with specific hashtags. Returns unique, deduplicated user profiles. | Parameter | Type | Required | Description | |-----------|------|----------|-------------| | `hashtags` | string[] | Yes | Array of hashtags (1-5). Bare alphanumeric/underscore only -- do not include `#`. OR semantics: matches users who posted with **any** of the listed hashtags. | | `responseType` | string | No | `"fast"` (default), `"paging"`, or `"csv"`. See [Response Modes](/mcp/response-modes). | | `limit` | number | No | Max results. Fast: capped at 300. Paging/CSV: max 500,000. | | `startDate` | string | No | Start date filter (`YYYY-MM-DD`). | | `endDate` | string | No | End date filter (`YYYY-MM-DD`). | | `fields` | string[] | No | Fields to return. Includes user fields plus aggregation fields. | | `pageNumber` | integer | No | Page to fetch (1-indexed). Requires `tableName` for pages > 1. | | `pageNumberEnd` | integer | No | End page for bulk fetching. Must be >= `pageNumber`. | | `tableName` | string | No | Cached table name from a previous pagination response. | | `forceLatest` | boolean | No | Force fresh data from API. Default: `false`. | **Example `hashtags` values:** `["dance", "fyp"]`, `["cooking"]`, `["sustainable_fashion"]` Pass bare alphanumeric tags only -- no leading `#`. Each hashtag must match the pattern `[A-Za-z0-9_]` with a max length of 500 characters. ### getTiktokPostsByUser Get posts from a TikTok user by ID or username. | Parameter | Type | Required | Description | |-----------|------|----------|-------------| | `identifier` | string | Yes | User ID (numeric) or username. | | `identifierType` | string | Yes | `"id"` or `"username"`. | | `responseType` | string | No | `"fast"` (default), `"paging"`, or `"csv"`. See [Response Modes](/mcp/response-modes). | | `limit` | number | No | Max results. Fast: capped at 300. Paging/CSV: max 500,000. | | `startDate` | string | No | Start date filter (`YYYY-MM-DD`). | | `endDate` | string | No | End date filter (`YYYY-MM-DD`). | | `fields` | string[] | No | Fields to return. | | `pageNumber` | integer | No | Page to fetch (1-indexed). | | `pageNumberEnd` | integer | No | End page for bulk fetching. | | `tableName` | string | No | Cached table name from a previous pagination response. | | `forceLatest` | boolean | No | Force fresh data from API. Default: `false`. | Data older than 1 week is automatically refreshed. Supports server-side pagination with 100 posts per page. See [Pagination](/mcp/pagination) for details. ### getTiktokPostsByHashtags Search TikTok posts by hashtags. Searches the indexed `hashtags` column directly (not post descriptions). | Parameter | Type | Required | Description | |-----------|------|----------|-------------| | `hashtags` | string[] | Yes | Array of hashtags (1-5). Bare alphanumeric/underscore only -- do not include `#`. OR semantics: matches posts containing **any** of the listed hashtags. | | `responseType` | string | No | `"fast"` (default), `"paging"`, or `"csv"`. See [Response Modes](/mcp/response-modes). | | `limit` | number | No | Max results. Fast: capped at 300. Paging/CSV: max 500,000. | | `startDate` | string | No | Start date filter (`YYYY-MM-DD`). | | `endDate` | string | No | End date filter (`YYYY-MM-DD`). | | `fields` | string[] | No | Fields to return. | | `pageNumber` | integer | No | Page to fetch (1-indexed). | | `pageNumberEnd` | integer | No | End page for bulk fetching. | | `tableName` | string | No | Cached table name from a previous pagination response. | | `forceLatest` | boolean | No | Force fresh data from API. Default: `false`. | **Example `hashtags` values:** `["dance", "fyp", "viral"]`, `["cooking"]`, `["sustainable_fashion"]` Pass bare alphanumeric tags only -- no leading `#`. Each hashtag must match the pattern `[A-Za-z0-9_]` with a max length of 500 characters. Use `getTiktokPostsByHashtags` for precise hashtag matching. Use `getTiktokPostsByKeywords` when searching for terms in post descriptions and transcripts. --- # Tracking Tools Source: https://docs.xpoz.ai/mcp/tools/tracking Xpoz provides **3 tools** for managing tracked items. Tracked items are monitored continuously, ensuring fresh data is available for your searches. ## Tracked Item Schema Every tracked item has three fields: | Field | Type | Values | Description | |-------|------|--------|-------------| | `phrase` | string | Any non-empty string | The keyword, username, subreddit name, or hashtag to track. | | `type` | string | `"keyword"`, `"user"`, `"subreddit"`, `"hashtag"` | Type of item. `"subreddit"` is Reddit-only. `"hashtag"` is TikTok-only. | | `platform` | string | `"twitter"`, `"instagram"`, `"reddit"`, `"tiktok"` | Target platform. | The number of tracked items is limited by your plan. Use `getAccountDetails` to check your current limits and usage. ### addTrackedItems Add keywords, users, subreddits, or hashtags to track. | Parameter | Type | Required | Description | |-----------|------|----------|-------------| | `items` | TrackedItem[] | Yes | Array of items to track (minimum 1). Each item has `phrase`, `type`, and `platform`. | | `feedback` | string | No | Free-form product feedback. | **Example `items` value:** ```json [ { "phrase": "AI agents", "type": "keyword", "platform": "twitter" }, { "phrase": "elonmusk", "type": "user", "platform": "twitter" }, { "phrase": "wallstreetbets", "type": "subreddit", "platform": "reddit" }, { "phrase": "machinelearning", "type": "hashtag", "platform": "tiktok" } ] ``` Returns an error if adding the items would exceed your plan's tracking limit. ## Platform and Type Compatibility | Type | Twitter | Instagram | Reddit | TikTok | |------|---------|-----------|--------|--------| | `keyword` | Yes | Yes | Yes | Yes | | `user` | Yes | Yes | Yes | Yes | | `subreddit` | -- | -- | Yes | -- | | `hashtag` | -- | -- | -- | Yes | --- # Account & Auth Tools Source: https://docs.xpoz.ai/mcp/tools/account Xpoz provides **6 tools** for account management, authentication, and operation tracking. This page covers the 3 account/auth tools. For operation management, see [Operations](/mcp/operations). ## Account Tools ### getAccountDetails Get the authenticated user's account details including plan information, billing status, and usage metrics. | Parameter | Type | Required | Description | |-----------|------|----------|-------------| | `feedback` | string | No | Free-form product feedback (does not affect tool behavior). | **Response includes:** | Field | Description | |-------|-------------| | `plan` | Plan name and full features object. | | `billing` | Billing period and next renewal date. `null` for Free plan users. | | `usage` | Subscription credits remaining, extra credits remaining, and extra tracked items purchased on top of the plan. | This tool requires authentication. It returns your current plan details and usage statistics. ### checkAccessKeyStatus Check the status of your access key without revealing the key itself. | Parameter | Type | Required | Description | |-----------|------|----------|-------------| | `feedback` | string | No | Free-form product feedback. | **Response includes:** | Field | Description | |-------|-------------| | `hasAccessKey` | Whether an active access key exists. | | `keyName` | Name of the key. | | `createdAt` | ISO 8601 creation timestamp. | | `expiryInfo` | Expiration date or "No expiration". | | `provider` | Auth provider. | | `isActive` | Whether the key is currently active. | Use `checkAccessKeyStatus` to verify your key is active before making calls. Use `getUserAccessKey` only when you need the actual key value. --- # TypeScript SDK Quickstart Source: https://docs.xpoz.ai/sdks/typescript/quickstart ## Installation ```bash npm install @xpoz/xpoz ``` Requires Node.js 18+. ## Get an Access Key Sign up and get your token at [xpoz.ai/get-token](https://xpoz.ai/get-token). **Start instantly — no account needed.** Generate a free token and use it as your API key: ```bash curl -s -X POST https://api.xpoz.ai/api/trial/token \ -H "Content-Type: application/json" \ -d '{"source": ""}' | jq -r .data.accessKey # -> TRIAL... (valid 5 days, all read tools across 4 platforms) ``` This returns a preview of up to 5 results per call. To get full data, pagination, and CSV export, [create a free account](https://xpoz.ai/get-token) — no credit card required. ## Create a Client ```typescript import { XpozClient } from "@xpoz/xpoz"; // Pass access key directly const client = new XpozClient({ apiKey: "your-api-key" }); await client.connect(); // Or use the XPOZ_API_KEY environment variable const client = new XpozClient(); await client.connect(); ``` ### Configuration Options | Option | Type | Default | Description | | --- | --- | --- | --- | | `apiKey` | `string` | `process.env.XPOZ_API_KEY` | Access key for authentication | | `serverUrl` | `string` | `https://mcp.xpoz.ai/mcp` | MCP server URL | | `timeoutMs` | `number` | `300000` | Operation timeout in milliseconds | ```typescript const client = new XpozClient({ apiKey: "your-api-key", serverUrl: "https://mcp.xpoz.ai/mcp", timeoutMs: 600_000, // 10 minutes }); await client.connect(); ``` ## Your First Call ```typescript import { XpozClient } from "@xpoz/xpoz"; const client = new XpozClient({ apiKey: "your-api-key" }); await client.connect(); // Get a Twitter user profile const user = await client.twitter.getUser("elonmusk"); console.log(`${user.name} — ${user.followersCount?.toLocaleString()} followers`); // Search for posts const results = await client.twitter.searchPosts("artificial intelligence", { startDate: "2025-01-01", }); for (const post of results.data) { console.log(post.text, post.likeCount); } await client.close(); ``` ## Connection Lifecycle You must call `connect()` before making any calls and `close()` when done. ### Manual connect/close ```typescript const client = new XpozClient({ apiKey: "your-api-key" }); await client.connect(); try { const results = await client.twitter.searchPosts("AI"); } finally { await client.close(); } ``` ### Async disposal (recommended) With TypeScript 5.2+ or Node.js 18.2+ (with `--experimental-vm-modules`), you can use `Symbol.asyncDispose` to auto-close the client: ```typescript await using client = new XpozClient({ apiKey: "your-api-key" }); await client.connect(); const user = await client.twitter.getUser("elonmusk"); // client.close() is called automatically when the block exits ``` ## Field Selection All methods accept a `fields` option. Requesting fewer fields significantly improves response time. ```typescript const results = await client.twitter.searchPosts("AI", { fields: ["id", "text", "likeCount", "retweetCount", "createdAtDate"], }); const user = await client.twitter.getUser("elonmusk", { fields: ["id", "username", "name", "followersCount", "description"], }); ``` Use `fields` to request only the data you need. This reduces response time and memory usage, especially for large result sets. ## Query Syntax The `query` parameter on `searchPosts`, `getUsersByKeywords`, and similar methods supports Lucene-style full-text search: ```typescript // Exact phrase await client.twitter.searchPosts('"machine learning"'); // Boolean operators await client.twitter.searchPosts('"deep learning" AND python'); await client.twitter.searchPosts("tensorflow OR pytorch"); await client.twitter.searchPosts("climate AND policy"); // Grouping await client.twitter.searchPosts('(AI OR "artificial intelligence") AND ethics'); ``` Do not use `from:`, `lang:`, `since:`, or `until:` in the query string. Use the dedicated parameters (`authorUsername`, `language`, `startDate`, `endDate`) instead. ## Environment Variables | Variable | Description | Default | | --- | --- | --- | | `XPOZ_API_KEY` | Access key for authentication | -- | | `XPOZ_SERVER_URL` | MCP server URL | `https://mcp.xpoz.ai/mcp` | ## Next Steps - [Pagination](/sdks/typescript/pagination) -- navigate large result sets and export CSV - [Error Handling](/sdks/typescript/error-handling) -- handle errors gracefully - [SDK Reference](/sdks/typescript/reference) -- full list of methods and type models - [Python SDK Quickstart](/sdks/python/quickstart) -- equivalent guide for the Python SDK --- # TypeScript SDK Pagination Source: https://docs.xpoz.ai/sdks/typescript/pagination ## PaginatedResult Methods that return large datasets use server-side pagination (100 items per page). These return a `PaginatedResult` with built-in navigation helpers. ```typescript const results = await client.twitter.searchPosts("AI"); // Access current page data results.data; // TwitterPost[] — current page items results.pagination.totalRows; // total matching rows results.pagination.totalPages; // total pages results.pagination.pageNumber; // current page number results.pagination.pageSize; // items per page (100) results.pagination.resultsCount; // items on current page results.hasNextPage(); // boolean ``` ### Navigating Pages ```typescript const results = await client.twitter.searchPosts("AI"); // Fetch the next page if (results.hasNextPage()) { const page2 = await results.nextPage(); console.log(page2.data); // next 100 items } // Jump to a specific page const page5 = await results.getPage(5); ``` ### Exporting to CSV Any paginated result can be exported to CSV. This triggers a server-side export and returns a download URL: ```typescript const results = await client.twitter.searchPosts("AI"); const csvUrl = await results.exportCsv(); console.log(csvUrl); // URL to download the CSV file ``` ## Response Types Search and query methods support a `responseType` option that controls how results are returned. Import the `ResponseType` enum: ```typescript import { XpozClient, ResponseType } from "@xpoz/xpoz"; ``` | Mode | Enum Value | Behavior | Best For | | --- | --- | --- | --- | | **Fast** | `ResponseType.Fast` | Returns up to 300 results immediately, no async polling | Quick queries, UI previews | | **Paging** | `ResponseType.Paging` | Async paginated query with full dataset access | Full analysis, large datasets | | **CSV** | `ResponseType.Csv` | Async bulk export, returns download URL via `exportCsv()` | Data exports | ### Fast Mode (default) Returns results immediately without polling. Use `limit` to constrain the number of results (max 300): ```typescript const results = await client.twitter.searchPosts("bitcoin", { startDate: "2025-01-01", responseType: ResponseType.Fast, limit: 50, }); console.log(results.data.length); // up to 50 results, returned immediately ``` Fast mode skips async operation polling, making it significantly faster for small result sets. Use it when you need a quick preview or only need a limited number of results. ### Paging Mode Returns paginated results with full `totalRows`, `totalPages`, and navigation helpers: ```typescript const results = await client.twitter.searchPosts("bitcoin", { startDate: "2025-01-01", responseType: ResponseType.Paging, }); console.log(results.pagination.totalRows); // total matching rows if (results.hasNextPage()) { const page2 = await results.nextPage(); } ``` ### CSV Mode Initiates an async export. Call `exportCsv()` on the result to poll the export operation and get a download URL: ```typescript const results = await client.twitter.searchPosts("bitcoin", { startDate: "2025-01-01", responseType: ResponseType.Csv, }); const downloadUrl = await results.exportCsv(); console.log(downloadUrl); // URL to download the CSV file ``` ## Methods Supporting Response Types The following methods accept both `responseType` and `limit`: - `twitter.getPostsByAuthor()`, `twitter.searchPosts()`, `twitter.getUsersByKeywords()` - `instagram.getPostsByUser()`, `instagram.searchPosts()`, `instagram.getUsersByKeywords()` - `reddit.searchPosts()` - `tiktok.getPostsByUser()`, `tiktok.searchPosts()`, `tiktok.getUsersByKeywords()`, `tiktok.getPostsByHashtags()`, `tiktok.getUsersByHashtags()` These methods accept `limit` only (no `responseType`): - `twitter.searchUsers()`, `instagram.searchUsers()`, `reddit.searchUsers()`, `reddit.searchSubreddits()`, `tiktok.searchUsers()` For the equivalent pagination patterns in Python, see [Python SDK Pagination](/sdks/python/pagination). The Python SDK uses `ResponseType.FAST`, `ResponseType.PAGING`, and `ResponseType.CSV` (uppercase enum values) and snake_case field names. Instagram live methods (`client.instagramLive`) page differently — they use an opaque forward-only cursor with no page numbers or totals. See [TypeScript SDK Live Data](/sdks/typescript/live-data). --- # TypeScript SDK Live Data Source: https://docs.xpoz.ai/sdks/typescript/live-data ## What Live Data Is Most SDK methods read from the Xpoz database, topping up from the crawler when results look stale. The `instagramLive` namespace is different: it **bypasses the database entirely** and fetches straight from the crawler API, so every call returns what Instagram is serving right now. That trade-off is deliberate: | | `client.instagram` | `client.instagramLive` | |---|---|---| | Source | Database, topped up on demand | Crawler API only | | Freshness | May be minutes to days old | Current | | Speed | Fast (indexed reads) | Slower (live fetch per call) | | Pagination | Page numbers, totals, CSV export | Cursor only | | Trial access | Yes | No | Reach for `instagramLive` when freshness matters more than latency — checking a post's engagement right now, or pulling a follower list that changed this morning. For analysis over large historical sets, the database-backed methods are faster and support CSV export. Live methods require a paid account. They always trigger a live fetch, so they are not available on trial access and throw `AuthenticationError` (HTTP 403). ## No connect() Required Live methods talk to the Xpoz REST API rather than the MCP server, so they work without opening an MCP session: ```typescript import { XpozClient } from "@xpoz/xpoz"; const client = new XpozClient({ apiKey: "your-api-key" }); // No await client.connect() needed for live methods const page = await client.instagramLive.searchPosts("travel"); ``` You still need `connect()` before using any other namespace (`client.instagram`, `client.twitter`, and so on). ## CursorResult Live methods return a `CursorResult` rather than the `PaginatedResult` used elsewhere. The upstream API pages with an opaque **cursor** and reports no totals, so there is no page number, no `totalPages`, and no `getPage(n)`. ```typescript const page = await client.instagramLive.searchPosts("travel", { fields: ["id", "caption"] }); page.data; // InstagramPost[] — this page page.hasMore; // another page is available upstream page.nextPageCursor; // opaque token for the next call page.hasNextPage(); // boolean ``` ### Navigating Pages ```typescript const page = await client.instagramLive.searchPosts("travel"); // One page at a time if (page.hasNextPage()) { const next = await page.nextPage(); } // Or walk every page for await (const post of page.items()) { console.log(post.id); } // Or page by page for await (const p of page.pages()) { console.log(`${p.data.length} posts`); } ``` Drive pagination off `hasMore` and the cursor — **never off the item count**. The upstream API may return a short or even empty page while `hasMore` is still `true`. Stopping when a page looks empty will cut your results short. ```typescript // Correct let page = await client.instagramLive.searchPosts("travel"); while (page.hasNextPage()) { page = await page.nextPage(); process(page.data); } // Wrong — stops early on a legitimately empty page while (page.data.length > 0) { page = await page.nextPage(); } ``` ## Methods All methods accept `fields` to select which fields come back, and all paged methods accept `cursor` to resume from a previous response. | Method | Returns | |---|---| | `searchPosts(query, options?)` | `CursorResult` | | `getPostsByUser(identifier, options?)` | `CursorResult` | | `getPost(postId, options?)` | `InstagramPost \| null` | | `getComments(postId, options?)` | `CursorResult` | | `getPostInteractingUsers(postId, interactionType, options?)` | `CursorResult` | | `searchUsers(name, options?)` | `CursorResult` | | `getUser(identifier, options?)` | `InstagramUser \| null` | | `getUserConnections(identifier, connectionType, options?)` | `CursorResult` | `interactionType` is `"commenters"` or `"likers"`. `connectionType` is `"followers"` or `"following"`. Both are typed unions, so invalid values fail at compile time. `getPost` and `getUser` are single-item lookups and return the object directly, or `null` if nothing was found. ### Examples ```typescript import { XpozClient } from "@xpoz/xpoz"; const client = new XpozClient({ apiKey: "your-api-key" }); // Search posts by keyword const posts = await client.instagramLive.searchPosts("travel", { fields: ["id", "caption", "likeCount"], }); // A user's recent posts const userPosts = await client.instagramLive.getPostsByUser("natgeo", { fields: ["id", "likeCount"] }); // Who liked a post const likers = await client.instagramLive.getPostInteractingUsers( "3820275679950397949_495767729", "likers", { fields: ["id", "username"] } ); // Who a user follows const following = await client.instagramLive.getUserConnections("natgeo", "following", { fields: ["username"], }); // Single lookups const post = await client.instagramLive.getPost("3820275679950397949_495767729"); const user = await client.instagramLive.getUser("natgeo"); ``` ### Resuming From a Cursor Cursors are opaque strings you can persist and reuse later, which is useful for long-running or resumable jobs: ```typescript const page = await client.instagramLive.searchPosts("travel"); const savedCursor = page.nextPageCursor; // Later, in another process const resumed = await client.instagramLive.searchPosts("travel", { cursor: savedCursor ?? undefined }); ``` A cursor is only valid for the same query on the same endpoint. Reusing one elsewhere is rejected with a `400`. ## Field Selection Live methods accept the same `fields` values as their database-backed counterparts — see the [TypeScript SDK Reference](/sdks/typescript/reference) for the full Instagram field lists. Live methods do **not** support `since` / `until` date filtering. The upstream API accepts only the query and a cursor, so use `client.instagram.searchPosts()` when you need a date range. ## Connection Details Live methods talk to the Xpoz REST API (`https://api.xpoz.ai`) rather than the MCP server, using the same API key. Override the base URL when needed: ```typescript const client = new XpozClient({ apiKey: "your-api-key", apiUrl: "https://api.xpoz.ai" }); ``` The `XPOZ_API_URL` environment variable does the same thing. --- # TypeScript SDK Error Handling Source: https://docs.xpoz.ai/sdks/typescript/error-handling ## Error Hierarchy All SDK errors extend from `XpozError`. Import them from the package: ```typescript import { XpozError, AuthenticationError, XpozConnectionError, OperationTimeoutError, OperationFailedError, OperationCancelledError, } from "@xpoz/xpoz"; ``` | Error Class | When It's Thrown | | --- | --- | | `XpozError` | Base class for all Xpoz errors | | `AuthenticationError` | Invalid or missing access key | | `XpozConnectionError` | Cannot connect to the MCP server | | `OperationTimeoutError` | Operation exceeded the configured timeout | | `OperationFailedError` | Operation failed server-side | | `OperationCancelledError` | Operation was cancelled | ## Catching Errors Use `instanceof` checks to handle specific error types. Always catch more specific errors before the base `XpozError`: ```typescript try { const user = await client.twitter.getUser("nonexistent_user_12345"); } catch (e) { if (e instanceof OperationFailedError) { console.log(`Operation ${e.operationId} failed: ${e.operationError}`); } else if (e instanceof OperationTimeoutError) { console.log(`Timed out after ${Math.round(e.elapsedMs / 1000)}s`); } else if (e instanceof AuthenticationError) { console.log("Invalid access key"); } else if (e instanceof XpozConnectionError) { console.log("Cannot connect to MCP server"); } else if (e instanceof XpozError) { console.log(`Xpoz error: ${e.message}`); } } ``` ## Error Details ### AuthenticationError Thrown when the access key is invalid, expired, or missing. ```typescript try { const client = new XpozClient({ apiKey: "invalid-key" }); await client.connect(); await client.twitter.getUser("elonmusk"); } catch (e) { if (e instanceof AuthenticationError) { console.log(e.message); // "Invalid access key" or similar } } ``` ### OperationTimeoutError Thrown when an operation exceeds the configured timeout (default: 300,000ms / 5 minutes). The error includes the elapsed time. ```typescript try { const results = await client.twitter.searchPosts("very broad query"); } catch (e) { if (e instanceof OperationTimeoutError) { console.log(`Timed out after ${Math.round(e.elapsedMs / 1000)}s`); // Consider narrowing your query or increasing timeoutMs } } ``` If you frequently hit timeouts, increase the timeout when creating the client: `new XpozClient({ timeoutMs: 600_000 })`. You can also narrow your queries with date filters, field selection, or more specific search terms. ### OperationFailedError Thrown when an operation completes but with an error status. Includes the `operationId` and error details. ```typescript try { const results = await client.twitter.searchPosts("query"); } catch (e) { if (e instanceof OperationFailedError) { console.log(`Operation: ${e.operationId}`); console.log(`Error: ${e.operationError}`); } } ``` ### OperationCancelledError Thrown when an operation is cancelled, typically due to server-side resource management. ```typescript try { const results = await client.twitter.searchPosts("query"); } catch (e) { if (e instanceof OperationCancelledError) { console.log(`Operation ${e.operationId} was cancelled`); } } ``` ## Practical Pattern A robust wrapper that handles all error cases: ```typescript import { XpozClient, XpozError, AuthenticationError, OperationTimeoutError, OperationFailedError, OperationCancelledError, } from "@xpoz/xpoz"; async function searchWithRetry(client: XpozClient, query: string): Promise { try { const results = await client.twitter.searchPosts(query, { startDate: "2025-01-01", }); console.log(`Found ${results.pagination.totalRows} results`); for (const post of results.data) { console.log(`${post.authorUsername}: ${post.text}`); } } catch (e) { if (e instanceof AuthenticationError) { throw e; // Cannot recover — propagate to caller } else if (e instanceof OperationTimeoutError) { console.log("Query timed out — try narrowing the date range or query"); } else if (e instanceof OperationFailedError) { console.log(`Server error: ${e.operationError}`); } else if (e instanceof OperationCancelledError) { console.log("Operation cancelled — retrying may help"); } else if (e instanceof XpozError) { console.log(`Unexpected Xpoz error: ${e.message}`); } else { throw e; // Not an Xpoz error — rethrow } } } ``` For the equivalent error handling patterns in Python, see [Python SDK Error Handling](/sdks/python/error-handling). The Python SDK uses `try/except` with the same error hierarchy but Python exception classes (`OperationFailedError`, `OperationTimeoutError`, etc.). --- # TypeScript SDK Reference Source: https://docs.xpoz.ai/sdks/typescript/reference ## Twitter — `client.twitter` ### Available Fields #### User Fields Pass these in the `options.fields` parameter on any user method. **Default:** `id`, `username`, `name` | Category | Fields | |----------|--------| | **Identity** | `id`, `username`, `name`, `description`, `location`, `profileImageUrl`, `profileBannerUrl` | | **Verification** | `verified`, `isVerified`, `verifiedType`, `verifiedSinceDatetime` | | **Metrics** | `followersCount`, `followingCount`, `tweetCount`, `listedCount`, `likesCount`, `mediaCount` | | **Metadata** | `pinnedTweetId`, `source`, `label`, `labelType`, `accountBasedIn`, `locationAccurate` | | **History** | `usernameChanges`, `lastUsernameChangeDatetime`, `createdAt` | `getUsersByKeywords` also returns aggregation fields: `aggRelevance`, `relevantTweetsCount`, `relevantTweetsImpressionsSum`, `relevantTweetsLikesSum`, `relevantTweetsQuotesSum`, `relevantTweetsRepliesSum`, `relevantTweetsRetweetsSum`. #### Post Fields Pass these in the `options.fields` parameter on any post method. **Default:** `id`, `text`, `authorUsername`, `createdAtDate` | Category | Fields | |----------|--------| | **Core** | `id`, `text`, `authorId`, `authorUsername`, `createdAt`, `createdAtDate` | | **Engagement** | `retweetCount`, `replyCount`, `likeCount`, `quoteCount`, `impressionCount`, `bookmarkCount` | | **Metadata** | `lang`, `possiblySensitive`, `suspended`, `deleted`, `source`, `isRetweet`, `hasBirdwatchNotes`, `status` | | **Birdwatch** | `birdwatchNotesId`, `birdwatchNotesText`, `birdwatchNotesUrl` | | **Relations** | `conversationId`, `quotedTweetId`, `retweetedTweetId`, `replyToTweetId`, `replyToUserId`, `replyToUsername`, `originalTweetId`, `editedTweets` | | **Content** | `hashtags`, `mentions`, `mediaUrls`, `urls`, `grokGeneratedContent` | | **Location** | `country`, `region`, `city` | Always specify only the fields you need using the `fields` parameter. For example, `["id", "text", "retweetCount", "likeCount", "createdAtDate"]` for engagement analysis. See [Field Selection](/mcp/field-selection) for details. ### searchUsers Search users by name or username. ```typescript const users = await client.twitter.searchUsers("elon"); const topFive = await client.twitter.searchUsers("elon", { limit: 5 }); ``` | Parameter | Type | Required | Description | | --- | --- | --- | --- | | `name` | `string` | Yes | Name or username to search | | `options.limit` | `number` | No | Max results (default: 10) | | `options.fields` | `string[]` | No | Fields to return | **Returns:** `Promise` ### getUsersByKeywords Find users who authored posts matching a keyword query. ```typescript const users = await client.twitter.getUsersByKeywords('"machine learning"', { fields: ["username", "name", "followersCount"], responseType: ResponseType.Fast, limit: 20, }); ``` | Parameter | Type | Required | Description | | --- | --- | --- | --- | | `query` | `string` | Yes | Keyword query (supports boolean operators) | | `options.fields` | `string[]` | No | Fields to return | | `options.startDate` | `string` | No | Start date (YYYY-MM-DD) | | `options.endDate` | `string` | No | End date (YYYY-MM-DD) | | `options.language` | `string` | No | Language filter | | `options.responseType` | `ResponseType` | No | Response mode | | `options.limit` | `number` | No | Max results (fast mode) | **Returns:** `Promise>` ### getPostsByAuthor Get all posts by an author with optional date filtering. ```typescript const results = await client.twitter.getPostsByAuthor("elonmusk", { startDate: "2025-01-01", responseType: ResponseType.Fast, limit: 100, }); ``` | Parameter | Type | Required | Description | | --- | --- | --- | --- | | `identifier` | `string` | Yes | Username or user ID | | `options.identifierType` | `"username" \| "id"` | No | Identifier type (default: `"username"`) | | `options.fields` | `string[]` | No | Fields to return | | `options.startDate` | `string` | No | Start date (YYYY-MM-DD) | | `options.endDate` | `string` | No | End date (YYYY-MM-DD) | | `options.responseType` | `ResponseType` | No | Response mode | | `options.limit` | `number` | No | Max results (fast mode) | **Returns:** `Promise>` ### getRetweets Get retweets of a specific post. ```typescript const retweets = await client.twitter.getRetweets("1234567890"); ``` | Parameter | Type | Required | Description | | --- | --- | --- | --- | | `postId` | `string` | Yes | Post ID | | `options.fields` | `string[]` | No | Fields to return | **Returns:** `Promise>` ### getComments Get replies to a specific post. ```typescript const comments = await client.twitter.getComments("1234567890"); ``` | Parameter | Type | Required | Description | | --- | --- | --- | --- | | `postId` | `string` | Yes | Post ID | | `options.fields` | `string[]` | No | Fields to return | **Returns:** `Promise>` ### countPosts Count tweets containing a phrase within a date range. ```typescript const count = await client.twitter.countPosts("bitcoin", { startDate: "2025-01-01" }); console.log(`${count.toLocaleString()} tweets mention bitcoin`); ``` | Parameter | Type | Required | Description | | --- | --- | --- | --- | | `phrase` | `string` | Yes | Phrase to count | | `options.startDate` | `string` | No | Start date (YYYY-MM-DD) | | `options.endDate` | `string` | No | End date (YYYY-MM-DD) | **Returns:** `Promise` ### getUser Get a single Instagram user profile. ```typescript const user = await client.instagram.getUser("instagram"); console.log(`${user.fullName} — ${user.followerCount?.toLocaleString()} followers`); ``` | Parameter | Type | Required | Description | | --- | --- | --- | --- | | `identifier` | `string` | Yes | Username or user ID | | `options.identifierType` | `"username" \| "id"` | No | Identifier type (default: `"username"`) | | `options.fields` | `string[]` | No | Fields to return | **Returns:** `Promise` ### getUserConnections Get followers or following for an Instagram user. ```typescript const followers = await client.instagram.getUserConnections("instagram", "followers"); ``` | Parameter | Type | Required | Description | | --- | --- | --- | --- | | `username` | `string` | Yes | Instagram username | | `connectionType` | `"followers" \| "following"` | Yes | Connection type | | `options.fields` | `string[]` | No | Fields to return | **Returns:** `Promise>` ### getPostsByIds Get Instagram posts by their IDs. Post IDs must be in strong_id format: `"media_id_user_id"`. ```typescript const posts = await client.instagram.getPostsByIds(["3606450040306139062_4836333238"]); ``` | Parameter | Type | Required | Description | | --- | --- | --- | --- | | `postIds` | `string[]` | Yes | Array of post IDs in strong_id format | | `options.fields` | `string[]` | No | Fields to return | **Returns:** `Promise` ### searchPosts Full-text search across Instagram posts. ```typescript const results = await client.instagram.searchPosts("travel photography", { responseType: ResponseType.Fast, limit: 30, }); ``` | Parameter | Type | Required | Description | | --- | --- | --- | --- | | `query` | `string` | Yes | Search query | | `options.fields` | `string[]` | No | Fields to return | | `options.startDate` | `string` | No | Start date (YYYY-MM-DD) | | `options.endDate` | `string` | No | End date (YYYY-MM-DD) | | `options.responseType` | `ResponseType` | No | Response mode | | `options.limit` | `number` | No | Max results (fast mode) | **Returns:** `Promise>` ### getPostInteractingUsers Get users who interacted with an Instagram post. ```typescript const likers = await client.instagram.getPostInteractingUsers( "3606450040306139062_4836333238", "likers" ); ``` | Parameter | Type | Required | Description | | --- | --- | --- | --- | | `postId` | `string` | Yes | Post ID (strong_id format) | | `interactionType` | `"commenters" \| "likers"` | Yes | Interaction type | | `options.fields` | `string[]` | No | Fields to return | **Returns:** `Promise>` ### getUser Get a single Reddit user profile. ```typescript const user = await client.reddit.getUser("spez"); console.log(`${user.username} — ${user.totalKarma?.toLocaleString()} karma`); ``` | Parameter | Type | Required | Description | | --- | --- | --- | --- | | `username` | `string` | Yes | Reddit username | | `options.fields` | `string[]` | No | Fields to return | **Returns:** `Promise` ### getUsersByKeywords Find Reddit users who authored posts matching a keyword query. ```typescript const users = await client.reddit.getUsersByKeywords('"machine learning"', { subreddit: "MachineLearning", }); ``` | Parameter | Type | Required | Description | | --- | --- | --- | --- | | `query` | `string` | Yes | Keyword query | | `options.fields` | `string[]` | No | Fields to return | | `options.startDate` | `string` | No | Start date (YYYY-MM-DD) | | `options.endDate` | `string` | No | End date (YYYY-MM-DD) | | `options.subreddit` | `string` | No | Filter to subreddit | **Returns:** `Promise>` ### getPostWithComments Get a Reddit post with its comments. ```typescript const result = await client.reddit.getPostWithComments("abc123"); console.log(result.post.title); for (const comment of result.comments) { console.log(` ${comment.authorUsername}: ${comment.body?.slice(0, 80)}`); } ``` | Parameter | Type | Required | Description | | --- | --- | --- | --- | | `postId` | `string` | Yes | Reddit post ID | | `options.fields` | `string[]` | No | Post fields to return | **Returns:** `Promise` The returned object contains: - `post` — `RedditPost` - `comments` — `RedditComment[]` - `commentsPagination` — `PaginationInfo | null` - `commentsTableName` — `string | null` ### searchSubreddits Search subreddits by name. ```typescript const subs = await client.reddit.searchSubreddits("machine learning"); const topFive = await client.reddit.searchSubreddits("machine learning", { limit: 5 }); ``` | Parameter | Type | Required | Description | | --- | --- | --- | --- | | `query` | `string` | Yes | Subreddit name to search | | `options.limit` | `number` | No | Max results | | `options.fields` | `string[]` | No | Fields to return | **Returns:** `Promise` ### getSubredditsByKeywords Find subreddits related to a keyword query. ```typescript const subs = await client.reddit.getSubredditsByKeywords("cryptocurrency"); ``` | Parameter | Type | Required | Description | | --- | --- | --- | --- | | `query` | `string` | Yes | Keyword query | | `options.fields` | `string[]` | No | Fields to return | | `options.startDate` | `string` | No | Start date (YYYY-MM-DD) | | `options.endDate` | `string` | No | End date (YYYY-MM-DD) | **Returns:** `Promise>` ### getUser Get a single TikTok user profile. ```typescript const user = await client.tiktok.getUser("charlidamelio"); console.log(`${user.nickname} — ${user.followerCount?.toLocaleString()} followers`); // By numeric ID const user = await client.tiktok.getUser("123456789", { identifierType: "id" }); ``` | Parameter | Type | Required | Description | | --- | --- | --- | --- | | `identifier` | `string` | Yes | Username or user ID | | `options.identifierType` | `"username" \| "id"` | No | Identifier type (default: `"username"`) | | `options.fields` | `string[]` | No | Fields to return | **Returns:** `Promise` ### getUsersByKeywords Find TikTok users who authored posts matching a keyword query. ```typescript const users = await client.tiktok.getUsersByKeywords('"machine learning"', { responseType: ResponseType.Fast, limit: 20, }); ``` | Parameter | Type | Required | Description | | --- | --- | --- | --- | | `query` | `string` | Yes | Keyword query | | `options.fields` | `string[]` | No | Fields to return | | `options.startDate` | `string` | No | Start date (YYYY-MM-DD) | | `options.endDate` | `string` | No | End date (YYYY-MM-DD) | | `options.responseType` | `ResponseType` | No | Response mode | | `options.limit` | `number` | No | Max results (fast mode) | **Returns:** `Promise>` ### getPostsByUser Get all posts by a TikTok user. ```typescript const results = await client.tiktok.getPostsByUser("charlidamelio", { startDate: "2025-01-01", responseType: ResponseType.Fast, limit: 50, }); ``` | Parameter | Type | Required | Description | | --- | --- | --- | --- | | `identifier` | `string` | Yes | Username or user ID | | `options.identifierType` | `"username" \| "id"` | No | Identifier type (default: `"username"`) | | `options.fields` | `string[]` | No | Fields to return | | `options.startDate` | `string` | No | Start date (YYYY-MM-DD) | | `options.endDate` | `string` | No | End date (YYYY-MM-DD) | | `options.responseType` | `ResponseType` | No | Response mode | | `options.limit` | `number` | No | Max results (fast mode) | **Returns:** `Promise>` ### getPostsByHashtags Search TikTok posts by hashtags. Pass bare alphanumeric tags (no leading `#`). Max 5 hashtags per request; OR semantics across the list. ```typescript const results = await client.tiktok.getPostsByHashtags(["dance", "fyp"], { responseType: ResponseType.Fast, limit: 50, }); ``` | Parameter | Type | Required | Description | | --- | --- | --- | --- | | `hashtags` | `string[]` | Yes | Hashtags to search (max 5, no `#` prefix) | | `options.fields` | `string[]` | No | Fields to return | | `options.startDate` | `string` | No | Start date (YYYY-MM-DD) | | `options.endDate` | `string` | No | End date (YYYY-MM-DD) | | `options.responseType` | `ResponseType` | No | Response mode | | `options.limit` | `number` | No | Max results (fast mode) | **Returns:** `Promise>` ### getComments Get comments on a TikTok post. ```typescript const comments = await client.tiktok.getComments("7123456789012345678"); ``` | Parameter | Type | Required | Description | | --- | --- | --- | --- | | `postId` | `string` | Yes | Post ID | | `options.fields` | `string[]` | No | Fields to return | **Returns:** `Promise>` ### addTrackedItems Add one or more items to track. ```typescript const result = await client.tracking.addTrackedItems([ { phrase: "bitcoin", type: TrackedItemType.Keyword, platform: TrackedItemPlatform.Twitter }, { phrase: "nasa", type: TrackedItemType.User, platform: TrackedItemPlatform.Instagram }, ]); console.log(`Added ${result.addedCount} items (${result.currentCount}/${result.maxTrackedItems} used)`); ``` | Parameter | Type | Required | Description | | --- | --- | --- | --- | | `items` | `TrackedItemInput[]` | Yes | Items to track | | `items[].phrase` | `string` | Yes | Keyword, username, or subreddit name | | `items[].type` | `TrackedItemType` | Yes | `Keyword`, `User`, or `Subreddit` | | `items[].platform` | `TrackedItemPlatform` | Yes | `Twitter`, `Instagram`, `Reddit`, or `Tiktok` | **Returns:** `Promise` ## Type Models All fields are optional. Unknown fields from the server are preserved on the object. ### TwitterPost | Field | Type | Description | | --- | --- | --- | | `id` | `string` | Post ID | | `text` | `string` | Post text content | | `authorId` | `string` | Author's user ID | | `authorUsername` | `string` | Author's username | | `likeCount` | `number` | Number of likes | | `retweetCount` | `number` | Number of retweets | | `replyCount` | `number` | Number of replies | | `quoteCount` | `number` | Number of quotes | | `impressionCount` | `number` | Number of impressions | | `bookmarkCount` | `number` | Number of bookmarks | | `lang` | `string` | Language code | | `hashtags` | `string[]` | Hashtags in tweet | | `mentions` | `string[]` | Mentioned usernames | | `mediaUrls` | `string[]` | Media attachment URLs | | `urls` | `string[]` | URLs in tweet text | | `country` | `string` | Country (if geo-tagged) | | `createdAt` | `string` | Creation timestamp | | `createdAtDate` | `string` | Creation date (YYYY-MM-DD) | | `conversationId` | `string` | Thread conversation ID | | `quotedTweetId` | `string` | ID of quoted tweet | | `replyToTweetId` | `string` | ID of parent tweet | | `possiblySensitive` | `boolean` | Sensitive content flag | | `isRetweet` | `boolean` | Whether this is a retweet | | `hasBirdwatchNotes` | `boolean` | Has community notes | | `birdwatchNotesId` | `string` | Birdwatch note ID | | `birdwatchNotesText` | `string` | Birdwatch note text | | `birdwatchNotesUrl` | `string` | Birdwatch note URL | | `status` | `string` | Tweet status | ### TwitterUser | Field | Type | Description | | --- | --- | --- | | `id` | `string` | User ID | | `username` | `string` | Username (handle) | | `name` | `string` | Display name | | `description` | `string` | Bio text | | `location` | `string` | Location string | | `verified` | `boolean` | Verification status | | `verifiedType` | `string` | Verification type | | `followersCount` | `number` | Number of followers | | `followingCount` | `number` | Number of following | | `tweetCount` | `number` | Total tweets | | `likesCount` | `number` | Total likes | | `profileImageUrl` | `string` | Profile picture URL | | `createdAt` | `string` | Account creation timestamp | | `accountBasedIn` | `string` | Account location | ### InstagramPost | Field | Type | Description | | --- | --- | --- | | `id` | `string` | Post ID (strong_id format) | | `caption` | `string` | Post caption | | `username` | `string` | Author username | | `fullName` | `string` | Author display name | | `likeCount` | `number` | Number of likes | | `commentCount` | `number` | Number of comments | | `reshareCount` | `number` | Number of reshares | | `videoPlayCount` | `number` | Video play count | | `mediaType` | `string` | Media type | | `imageUrl` | `string` | Image URL | | `videoUrl` | `string` | Video URL | | `createdAtDate` | `string` | Creation date | ### InstagramUser | Field | Type | Description | | --- | --- | --- | | `id` | `string` | User ID | | `username` | `string` | Username | | `fullName` | `string` | Display name | | `biography` | `string` | Bio text | | `isPrivate` | `boolean` | Private account | | `isVerified` | `boolean` | Verified status | | `followerCount` | `number` | Followers | | `followingCount` | `number` | Following | | `mediaCount` | `number` | Total posts | | `profilePicUrl` | `string` | Profile picture URL | ### InstagramComment | Field | Type | Description | | --- | --- | --- | | `id` | `string` | Comment ID | | `text` | `string` | Comment text | | `username` | `string` | Author username | | `parentPostId` | `string` | Parent post ID | | `likeCount` | `number` | Number of likes | | `childCommentCount` | `number` | Reply count | | `createdAtDate` | `string` | Creation date | ### RedditPost | Field | Type | Description | | --- | --- | --- | | `id` | `string` | Post ID | | `title` | `string` | Post title | | `selftext` | `string` | Post body text | | `authorUsername` | `string` | Author username | | `subredditName` | `string` | Subreddit name | | `score` | `number` | Net score | | `upvotes` | `number` | Upvote count | | `commentsCount` | `number` | Comment count | | `url` | `string` | Post URL | | `permalink` | `string` | Reddit permalink | | `isSelf` | `boolean` | Self post (text only) | | `over18` | `boolean` | NSFW flag | | `createdAtDate` | `string` | Creation date | ### RedditUser | Field | Type | Description | | --- | --- | --- | | `id` | `string` | User ID | | `username` | `string` | Username | | `totalKarma` | `number` | Total karma | | `linkKarma` | `number` | Link karma | | `commentKarma` | `number` | Comment karma | | `isGold` | `boolean` | Reddit Gold status | | `isMod` | `boolean` | Moderator status | | `profileDescription` | `string` | Profile bio | | `createdAtDate` | `string` | Account creation date | ### RedditComment | Field | Type | Description | | --- | --- | --- | | `id` | `string` | Comment ID | | `body` | `string` | Comment text | | `authorUsername` | `string` | Author username | | `parentPostId` | `string` | Parent post ID | | `score` | `number` | Net score | | `depth` | `number` | Nesting depth | | `isSubmitter` | `boolean` | Is OP | | `createdAtDate` | `string` | Creation date | ### RedditSubreddit | Field | Type | Description | | --- | --- | --- | | `id` | `string` | Subreddit ID | | `displayName` | `string` | Subreddit name | | `title` | `string` | Subreddit title | | `publicDescription` | `string` | Short description | | `description` | `string` | Full description | | `subscribersCount` | `number` | Subscriber count | | `activeUserCount` | `number` | Active users | | `over18` | `boolean` | NSFW flag | | `createdAtDate` | `string` | Creation date | ### TiktokPost | Field | Type | Description | | --- | --- | --- | | `id` | `string` | Post ID | | `description` | `string` | Post caption/description | | `descriptionLanguage` | `string` | Language of description | | `userId` | `string` | Author user ID | | `username` | `string` | Author username | | `nickname` | `string` | Author display name | | `likeCount` | `number` | Number of likes | | `commentCount` | `number` | Number of comments | | `playCount` | `number` | Video play count | | `collectCount` | `number` | Number of collects/saves | | `downloadCount` | `number` | Number of downloads | | `forwardCount` | `number` | Number of forwards/shares | | `videoThumbnail` | `string` | Thumbnail URL | | `videoUrl` | `string[]` | Array of video URLs | | `duration` | `number` | Video duration in seconds | | `hashtags` | `string[]` | Hashtags in the post | | `postType` | `number` | Post type code | | `isPrivate` | `boolean` | Private post flag | | `createdAt` | `string` | Creation timestamp | | `createdAtDate` | `string` | Creation date (YYYY-MM-DD) | ### TiktokUser | Field | Type | Description | | --- | --- | --- | | `id` | `string` | User ID | | `username` | `string` | Username | | `nickname` | `string` | Display name | | `signature` | `string` | Bio text | | `secUid` | `string` | Secure user ID | | `avatar` | `string` | Profile picture URL | | `isPrivate` | `boolean` | Private account | | `isVerified` | `boolean` | Verified status | | `followerCount` | `number` | Number of followers | | `followingCount` | `number` | Number of following | | `likeCount` | `number` | Total likes received | | `postCount` | `number` | Total posts | | `language` | `string` | Profile language | | `region` | `string` | Account region | | `createdAt` | `string` | Account creation date | ### TiktokComment | Field | Type | Description | | --- | --- | --- | | `id` | `string` | Comment ID | | `postId` | `string` | Parent post ID | | `userId` | `string` | Author user ID | | `username` | `string` | Author username | | `text` | `string` | Comment text | | `likeCount` | `number` | Number of likes | | `createdAt` | `string` | Creation timestamp | | `createdAtDate` | `string` | Creation date (YYYY-MM-DD) | ### TrackedItem | Field | Type | Description | | --- | --- | --- | | `phrase` | `string` | Keyword, username, or subreddit name | | `type` | `TrackedItemType` | `"keyword"`, `"user"`, or `"subreddit"` | | `platform` | `TrackedItemPlatform` | `"twitter"`, `"instagram"`, `"reddit"`, or `"tiktok"` | ### AddTrackedItemsResult | Field | Type | Description | | --- | --- | --- | | `success` | `boolean` | Whether the operation succeeded | | `addedCount` | `number` | Number of items added | | `message` | `string` | Status message | | `currentCount` | `number` | Total tracked items after addition | | `maxTrackedItems` | `number` | Plan limit for tracked items | | `planName` | `string` | Current plan name | ### RemoveTrackedItemsResult | Field | Type | Description | | --- | --- | --- | | `success` | `boolean` | Whether the operation succeeded | | `removedCount` | `number` | Number of items removed | | `message` | `string` | Status message | For the Python equivalent of these types, see [Python SDK Reference](/sdks/python/reference). The Python SDK uses Pydantic v2 models with snake_case field names (e.g., `like_count` instead of `likeCount`). --- # Python SDK Quickstart Source: https://docs.xpoz.ai/sdks/python/quickstart ## Installation ```bash pip install xpoz ``` Requires Python 3.10+. ## Get an Access Key Sign up and get your token at [xpoz.ai/get-token](https://xpoz.ai/get-token). **Start instantly — no account needed.** Generate a free token and use it as your API key: ```bash curl -s -X POST https://api.xpoz.ai/api/trial/token \ -H "Content-Type: application/json" \ -d '{"source": ""}' | jq -r .data.accessKey # -> TRIAL... (valid 5 days, all read tools across 4 platforms) ``` This returns a preview of up to 5 results per call. To get full data, pagination, and CSV export, [create a free account](https://xpoz.ai/get-token) — no credit card required. ## Create a Client The Python SDK provides both synchronous and asynchronous clients. ```python from xpoz import XpozClient # Pass access key directly client = XpozClient("your-api-key") # Or use the XPOZ_API_KEY environment variable client = XpozClient() ``` ```python from xpoz import AsyncXpozClient client = AsyncXpozClient("your-api-key") await client.connect() ``` ### Configuration Options | Parameter | Type | Default | Description | | --- | --- | --- | --- | | `api_key` | `str` | `os.environ["XPOZ_API_KEY"]` | Access key for authentication | | `server_url` | `str` | `https://mcp.xpoz.ai/mcp` | MCP server URL | | `timeout` | `int` | `300` | Operation timeout in seconds | ```python client = XpozClient( "your-api-key", server_url="https://mcp.xpoz.ai/mcp", timeout=600, # 10 minutes ) ``` ## Your First Call ```python from xpoz import XpozClient client = XpozClient("your-api-key") # Get a Twitter user profile user = client.twitter.get_user("elonmusk") print(f"{user.name} — {user.followers_count:,} followers") # Search for posts results = client.twitter.search_posts("artificial intelligence", start_date="2025-01-01") for tweet in results.data: print(tweet.text, tweet.like_count) client.close() ``` ```python import asyncio from xpoz import AsyncXpozClient async def main(): async with AsyncXpozClient("your-api-key") as client: # Get a Twitter user profile user = await client.twitter.get_user("elonmusk") print(f"{user.name} — {user.followers_count:,} followers") # Search for posts results = await client.twitter.search_posts( "artificial intelligence", start_date="2025-01-01" ) for tweet in results.data: print(tweet.text, tweet.like_count) asyncio.run(main()) ``` ## Context Managers Use context managers to automatically close the client when done. ```python with XpozClient("your-api-key") as client: user = client.twitter.get_user("elonmusk") # client.close() is called automatically ``` ```python async with AsyncXpozClient("your-api-key") as client: user = await client.twitter.get_user("elonmusk") results = await client.twitter.search_posts("AI") page2 = await results.next_page() # client is closed automatically ``` ## Field Selection All methods accept a `fields` parameter. Use snake_case field names -- the SDK automatically converts to camelCase for the API. ```python results = client.twitter.search_posts( "AI", fields=["id", "text", "like_count", "retweet_count", "created_at_date"], ) user = client.twitter.get_user( "elonmusk", fields=["id", "username", "name", "followers_count", "description"], ) ``` Requesting fewer fields significantly improves response time and reduces memory usage, especially for large result sets. ## Query Syntax The `query` parameter on `search_posts`, `get_users_by_keywords`, and similar methods supports Lucene-style full-text search: ```python # Exact phrase client.twitter.search_posts('"machine learning"') # Boolean operators client.twitter.search_posts('"deep learning" AND python') client.twitter.search_posts("tensorflow OR pytorch") client.twitter.search_posts("climate AND policy") # Grouping client.twitter.search_posts('(AI OR "artificial intelligence") AND ethics') # Combined with filters results = client.twitter.search_posts( '("machine learning" OR "deep learning") AND python', start_date="2025-01-01", language="en", ) ``` Do not use `from:`, `lang:`, `since:`, or `until:` in the query string. Use the dedicated parameters (`author_username`, `language`, `start_date`, `end_date`) instead. ## Environment Variables | Variable | Description | Default | | --- | --- | --- | | `XPOZ_API_KEY` | Access key for authentication | -- | | `XPOZ_SERVER_URL` | MCP server URL | `https://mcp.xpoz.ai/mcp` | ## Next Steps - [Pagination](/sdks/python/pagination) -- navigate large result sets and export CSV - [Error Handling](/sdks/python/error-handling) -- handle errors gracefully - [SDK Reference](/sdks/python/reference) -- full list of methods and type models - [TypeScript SDK Quickstart](/sdks/typescript/quickstart) -- equivalent guide for the TypeScript SDK --- # Python SDK Pagination Source: https://docs.xpoz.ai/sdks/python/pagination ## PaginatedResult Methods that return large datasets use server-side pagination (100 items per page). These return a `PaginatedResult[T]` (sync) or `AsyncPaginatedResult[T]` (async) with built-in navigation helpers. ```python results = client.twitter.search_posts("AI") # Access current page data results.data # list[TwitterPost] — current page items results.pagination.total_rows # total matching rows results.pagination.total_pages # total pages results.pagination.page_number # current page number results.pagination.page_size # items per page (100) results.pagination.results_count # items on current page results.has_next_page() # bool ``` ```python results = await client.twitter.search_posts("AI") # Same attributes, but navigation methods are awaited results.data # list[TwitterPost] results.pagination.total_rows # total matching rows results.has_next_page() # bool ``` ### Navigating Pages ```python results = client.twitter.search_posts("AI") # Fetch the next page if results.has_next_page(): page2 = results.next_page() print(page2.data) # next 100 items # Jump to a specific page page5 = results.get_page(5) ``` ```python results = await client.twitter.search_posts("AI") # Fetch the next page if results.has_next_page(): page2 = await results.next_page() # Jump to a specific page page5 = await results.get_page(5) ``` ### Exporting to CSV Any paginated result can be exported to CSV. This triggers a server-side export and returns a download URL. ```python results = client.twitter.search_posts("AI") csv_url = results.export_csv() print(csv_url) # URL to download the CSV file ``` ```python results = await client.twitter.search_posts("AI") csv_url = await results.export_csv() print(csv_url) ``` ## Response Types Methods that return `PaginatedResult` support a `response_type` parameter to control how results are fetched. Import the `ResponseType` enum: ```python from xpoz import XpozClient, ResponseType ``` | Mode | Enum Value | Behavior | Best For | | --- | --- | --- | --- | | **Fast** | `ResponseType.FAST` | Returns up to `limit` results immediately, no polling | Quick queries, UI previews | | **Paging** | `ResponseType.PAGING` | Async paginated query with full dataset access | Full analysis, large datasets | | **CSV** | `ResponseType.CSV` | Async bulk export, returns download URL via `export_csv()` | Data exports | ### Fast Mode (default) Returns results immediately without polling. This is the default behavior when `response_type` is not specified. ```python results = client.twitter.search_posts( "bitcoin", limit=10, fields=["id", "text", "like_count"], ) # Equivalent to response_type=ResponseType.FAST for tweet in results.data: print(tweet.text) ``` Fast mode skips async operation polling, making it significantly faster for small result sets. Use it when you need a quick preview or only need a limited number of results. ### Paging Mode Returns full paginated results (100 items per page). Use this when you need to iterate through all results. ```python results = client.twitter.search_posts( "bitcoin", response_type=ResponseType.PAGING, ) print(results.pagination.total_rows) # total matching rows ``` ### CSV Mode Triggers a server-side CSV export. The result contains no inline data -- call `export_csv()` to get the download URL. ```python results = client.twitter.search_posts( "bitcoin", response_type=ResponseType.CSV, ) csv_url = results.export_csv() print(csv_url) # URL to download the CSV file ``` ## Methods Supporting Response Types The following methods accept both `response_type` and `limit`: | Platform | Method | | --- | --- | | Twitter | `search_posts`, `get_posts_by_author`, `get_users_by_keywords` | | Instagram | `search_posts`, `get_posts_by_user`, `get_users_by_keywords` | | Reddit | `search_posts` | | TikTok | `search_posts`, `get_posts_by_user`, `get_users_by_keywords` | These methods accept `limit` only (no `response_type`): - `twitter.search_users()`, `instagram.search_users()`, `reddit.search_users()`, `reddit.search_subreddits()`, `tiktok.search_users()` For the equivalent pagination patterns in TypeScript, see [TypeScript SDK Pagination](/sdks/typescript/pagination). The TypeScript SDK uses `ResponseType.Fast`, `ResponseType.Paging`, and `ResponseType.Csv` (PascalCase enum values) and camelCase field names. Instagram live methods (`client.instagram_live`) page differently — they use an opaque forward-only cursor with no page numbers or totals. See [Python SDK Live Data](/sdks/python/live-data). --- # Python SDK Live Data Source: https://docs.xpoz.ai/sdks/python/live-data ## What Live Data Is Most SDK methods read from the Xpoz database, topping up from the crawler when results look stale. The `instagram_live` namespace is different: it **bypasses the database entirely** and fetches straight from the crawler API, so every call returns what Instagram is serving right now. That trade-off is deliberate: | | `client.instagram` | `client.instagram_live` | |---|---|---| | Source | Database, topped up on demand | Crawler API only | | Freshness | May be minutes to days old | Current | | Speed | Fast (indexed reads) | Slower (live fetch per call) | | Pagination | Page numbers, totals, CSV export | Cursor only | | Trial access | Yes | No | Reach for `instagram_live` when freshness matters more than latency — checking a post's engagement right now, or pulling a follower list that changed this morning. For analysis over large historical sets, the database-backed methods are faster and support CSV export. Live methods require a paid account. They always trigger a live fetch, so they are not available on trial access and raise `AuthenticationError` (HTTP 403). ## CursorResult Live methods return a `CursorResult[T]` rather than the `PaginatedResult[T]` used elsewhere. The upstream API pages with an opaque **cursor** and reports no totals, so there is no page number, no `total_pages`, and no `get_page(n)`. ```python page = client.instagram_live.search_posts("travel", fields=["id", "caption"]) page.data # list[InstagramPost] — this page page.has_more # bool — another page is available upstream page.next_page_cursor # opaque token for the next call page.has_next_page() # bool ``` ### Navigating Pages ```python page = client.instagram_live.search_posts("travel") # One page at a time if page.has_next_page(): page = page.next_page() # Or walk every page for post in page.iter_items(): print(post.id) ``` ```python page = await client.instagram_live.search_posts("travel") if page.has_next_page(): page = await page.next_page() async for post in page.iter_items(): print(post.id) ``` Drive pagination off `has_more` and the cursor — **never off the item count**. The upstream API may return a short or even empty page while `has_more` is still `true`. Stopping when a page looks empty will cut your results short. ```python # Correct while page.has_next_page(): page = page.next_page() process(page.data) # Wrong — stops early on a legitimately empty page while len(page.data) > 0: page = page.next_page() ``` ## Methods All methods accept `fields` to select which fields come back, and all paged methods accept `cursor` to resume from a previous response. | Method | Returns | |---|---| | `search_posts(query)` | `CursorResult[InstagramPost]` | | `get_posts_by_user(identifier)` | `CursorResult[InstagramPost]` | | `get_post(post_id)` | `InstagramPost \| None` | | `get_comments(post_id)` | `CursorResult[InstagramComment]` | | `get_post_interacting_users(post_id, interaction_type)` | `CursorResult[InstagramUser]` | | `search_users(name)` | `CursorResult[InstagramUser]` | | `get_user(identifier)` | `InstagramUser \| None` | | `get_user_connections(identifier, connection_type)` | `CursorResult[InstagramUser]` | `interaction_type` is `"commenters"` or `"likers"`. `connection_type` is `"followers"` or `"following"`. `get_post` and `get_user` are single-item lookups and return the object directly, or `None` if nothing was found. ### Examples ```python from xpoz import XpozClient client = XpozClient(api_key="your-api-key") # Search posts by keyword posts = client.instagram_live.search_posts("travel", fields=["id", "caption", "like_count"]) # A user's recent posts user_posts = client.instagram_live.get_posts_by_user("natgeo", fields=["id", "like_count"]) # Who liked a post likers = client.instagram_live.get_post_interacting_users( "3820275679950397949_495767729", "likers", fields=["id", "username"] ) # Who a user follows following = client.instagram_live.get_user_connections("natgeo", "following", fields=["username"]) # Single lookups post = client.instagram_live.get_post("3820275679950397949_495767729") user = client.instagram_live.get_user("natgeo") ``` ### Resuming From a Cursor Cursors are opaque strings you can persist and reuse later, which is useful for long-running or resumable jobs: ```python page = client.instagram_live.search_posts("travel") saved_cursor = page.next_page_cursor # Later, in another process page = client.instagram_live.search_posts("travel", cursor=saved_cursor) ``` A cursor is only valid for the same query on the same endpoint. Reusing one elsewhere is rejected with a `400`. ## Field Selection Live methods accept the same `fields` values as their database-backed counterparts — see the [Python SDK Reference](/sdks/python/reference) for the full Instagram field lists. Field names are snake_case and mapped automatically. Live methods do **not** support `since` / `until` date filtering. The upstream API accepts only the query and a cursor, so use `client.instagram.search_posts()` when you need a date range. ## Connection Details Live methods talk to the Xpoz REST API (`https://api.xpoz.ai`) rather than the MCP server, using the same API key. Override the base URL when needed: ```python client = XpozClient(api_key="your-api-key", api_url="https://api.xpoz.ai") ``` The `XPOZ_API_URL` environment variable does the same thing. --- # Python SDK Error Handling Source: https://docs.xpoz.ai/sdks/python/error-handling ## Exception Hierarchy All SDK exceptions extend from `XpozError`. Import them from the package: ```python from xpoz import ( XpozError, AuthenticationError, ConnectionError, OperationTimeoutError, OperationFailedError, OperationCancelledError, NotFoundError, ValidationError, ) ``` | Exception Class | When It's Raised | | --- | --- | | `XpozError` | Base class for all Xpoz exceptions | | `AuthenticationError` | Invalid or missing access key | | `ConnectionError` | Cannot connect to the MCP server | | `OperationTimeoutError` | Operation exceeded the configured timeout | | `OperationFailedError` | Operation failed server-side | | `OperationCancelledError` | Operation was cancelled | | `NotFoundError` | Requested resource was not found | | `ValidationError` | Invalid parameters passed to a method | The Python SDK includes two additional exception types not present in the TypeScript SDK: `NotFoundError` and `ValidationError`. These provide more granular error handling for common input issues. ## Catching Exceptions Use `except` clauses to handle specific exception types. Always catch more specific exceptions before the base `XpozError`: ```python try: user = client.twitter.get_user("nonexistent_user_12345") except OperationFailedError as e: print(f"Operation {e.operation_id} failed: {e.error}") except OperationTimeoutError as e: print(f"Timed out after {e.elapsed_seconds}s") except AuthenticationError: print("Invalid access key") except XpozError as e: print(f"Xpoz error: {e}") ``` ```python try: user = await client.twitter.get_user("nonexistent_user_12345") except OperationFailedError as e: print(f"Operation {e.operation_id} failed: {e.error}") except OperationTimeoutError as e: print(f"Timed out after {e.elapsed_seconds}s") except AuthenticationError: print("Invalid access key") except XpozError as e: print(f"Xpoz error: {e}") ``` ## Exception Details ### AuthenticationError Raised when the access key is invalid, expired, or missing. ```python try: client = XpozClient("invalid-key") client.twitter.get_user("elonmusk") except AuthenticationError as e: print(e) # "Invalid access key" or similar ``` ### OperationTimeoutError Raised when an operation exceeds the configured timeout (default: 300 seconds). The exception includes the elapsed time. ```python try: results = client.twitter.search_posts("very broad query") except OperationTimeoutError as e: print(f"Timed out after {e.elapsed_seconds}s") # Consider narrowing your query or increasing the timeout ``` If you frequently hit timeouts, increase the timeout when creating the client: `XpozClient("key", timeout=600)`. You can also narrow your queries with date filters, field selection, or more specific search terms. ### OperationFailedError Raised when an operation completes but with an error status. Includes the `operation_id` and error details. ```python try: results = client.twitter.search_posts("query") except OperationFailedError as e: print(f"Operation: {e.operation_id}") print(f"Error: {e.error}") ``` ### OperationCancelledError Raised when an operation is cancelled, typically due to server-side resource management. ```python try: results = client.twitter.search_posts("query") except OperationCancelledError as e: print(f"Operation {e.operation_id} was cancelled") ``` ### NotFoundError Raised when a requested resource (user, post, subreddit) does not exist. ```python try: user = client.twitter.get_user("definitely_not_a_real_user_12345") except NotFoundError: print("User not found") ``` ### ValidationError Raised when invalid parameters are passed to a method. ```python try: results = client.twitter.search_posts("") # empty query except ValidationError as e: print(f"Invalid input: {e}") ``` ## Practical Pattern A robust wrapper that handles all error cases: ```python from xpoz import ( XpozClient, XpozError, AuthenticationError, OperationTimeoutError, OperationFailedError, OperationCancelledError, ) def search_with_handling(client: XpozClient, query: str) -> None: try: results = client.twitter.search_posts(query, start_date="2025-01-01") print(f"Found {results.pagination.total_rows} results") for post in results.data: print(f"{post.author_username}: {post.text}") except AuthenticationError: raise # Cannot recover — propagate to caller except OperationTimeoutError: print("Query timed out — try narrowing the date range or query") except OperationFailedError as e: print(f"Server error: {e.error}") except OperationCancelledError: print("Operation cancelled — retrying may help") except XpozError as e: print(f"Unexpected Xpoz error: {e}") ``` ```python from xpoz import ( AsyncXpozClient, XpozError, AuthenticationError, OperationTimeoutError, OperationFailedError, OperationCancelledError, ) async def search_with_handling(client: AsyncXpozClient, query: str) -> None: try: results = await client.twitter.search_posts(query, start_date="2025-01-01") print(f"Found {results.pagination.total_rows} results") for post in results.data: print(f"{post.author_username}: {post.text}") except AuthenticationError: raise except OperationTimeoutError: print("Query timed out — try narrowing the date range or query") except OperationFailedError as e: print(f"Server error: {e.error}") except OperationCancelledError: print("Operation cancelled — retrying may help") except XpozError as e: print(f"Unexpected Xpoz error: {e}") ``` For the equivalent error handling patterns in TypeScript, see [TypeScript SDK Error Handling](/sdks/typescript/error-handling). The TypeScript SDK uses `try/catch` with `instanceof` checks instead of `try/except`. --- # Python SDK Reference Source: https://docs.xpoz.ai/sdks/python/reference All methods are available on both `XpozClient` (sync) and `AsyncXpozClient` (async). Async methods have the same signature but return awaitables. ## Twitter — `client.twitter` ### Available Fields The Python SDK accepts snake_case field names and automatically maps them to the camelCase names used by the underlying MCP server. #### User Fields Pass these in the `fields` parameter on any user method (`get_user`, `search_users`, `get_user_connections`, `get_users_by_keywords`, `get_post_interacting_users`). **Default:** `id`, `username`, `name` | Category | Fields | |----------|--------| | **Identity** | `id`, `username`, `name`, `description`, `location`, `profile_image_url`, `profile_banner_url` | | **Verification** | `verified`, `is_verified`, `verified_type`, `verified_since_datetime` | | **Metrics** | `followers_count`, `following_count`, `tweet_count`, `listed_count`, `likes_count`, `media_count` | | **Metadata** | `pinned_tweet_id`, `source`, `label`, `label_type`, `account_based_in`, `location_accurate` | | **History** | `username_changes`, `last_username_change_datetime`, `created_at` | `get_users_by_keywords` also returns aggregation fields: `agg_relevance`, `relevant_tweets_count`, `relevant_tweets_impressions_sum`, `relevant_tweets_likes_sum`, `relevant_tweets_quotes_sum`, `relevant_tweets_replies_sum`, `relevant_tweets_retweets_sum`. #### Post Fields Pass these in the `fields` parameter on any post method (`get_posts_by_ids`, `get_posts_by_author`, `search_posts`, `get_retweets`, `get_quotes`, `get_comments`). **Default:** `id`, `text`, `author_username`, `created_at_date` | Category | Fields | |----------|--------| | **Core** | `id`, `text`, `author_id`, `author_username`, `created_at`, `created_at_date` | | **Engagement** | `retweet_count`, `reply_count`, `like_count`, `quote_count`, `impression_count`, `bookmark_count` | | **Metadata** | `lang`, `possibly_sensitive`, `suspended`, `deleted`, `source`, `is_retweet`, `has_birdwatch_notes`, `status` | | **Birdwatch** | `birdwatch_notes_id`, `birdwatch_notes_text`, `birdwatch_notes_url` | | **Relations** | `conversation_id`, `quoted_tweet_id`, `retweeted_tweet_id`, `reply_to_tweet_id`, `reply_to_user_id`, `reply_to_username`, `original_tweet_id`, `edited_tweets` | | **Content** | `hashtags`, `mentions`, `media_urls`, `urls`, `grok_generated_content` | | **Location** | `country`, `region`, `city` | Always specify only the fields you need using the `fields` parameter. For example, `["id", "text", "retweet_count", "like_count", "created_at_date"]` for engagement analysis. See [Field Selection](/mcp/field-selection) for details. ### search_users Search users by name or username. ```python users = client.twitter.search_users("elon") top_five = client.twitter.search_users("elon", limit=5) ``` | Parameter | Type | Required | Description | | --- | --- | --- | --- | | `name` | `str` | Yes | Name or username to search | | `limit` | `int` | No | Max results (default: 10) | | `fields` | `list[str]` | No | Fields to return | **Returns:** `list[TwitterUser]` ### get_users_by_keywords Find users who authored posts matching a keyword query. Includes aggregation fields like `relevant_tweets_count` and `relevant_tweets_likes_sum`. ```python users = client.twitter.get_users_by_keywords( '"machine learning"', fields=["username", "name", "followers_count", "relevant_tweets_count"], response_type=ResponseType.FAST, limit=20, ) ``` | Parameter | Type | Required | Description | | --- | --- | --- | --- | | `query` | `str` | Yes | Keyword query (supports boolean operators) | | `fields` | `list[str]` | No | Fields to return | | `start_date` | `str` | No | Start date (YYYY-MM-DD) | | `end_date` | `str` | No | End date (YYYY-MM-DD) | | `language` | `str` | No | Language filter | | `force_latest` | `bool` | No | Force fresh data fetch | | `response_type` | `ResponseType` | No | Response mode | | `limit` | `int` | No | Max results (fast mode) | **Returns:** `PaginatedResult[TwitterUser]` ### get_posts_by_author Get all posts by an author with optional date filtering. ```python results = client.twitter.get_posts_by_author("elonmusk", start_date="2025-01-01") ``` ```python results = await client.twitter.get_posts_by_author("elonmusk", start_date="2025-01-01") ``` | Parameter | Type | Required | Description | | --- | --- | --- | --- | | `identifier` | `str` | Yes | Username or user ID | | `identifier_type` | `"username" \| "id"` | No | Identifier type (default: `"username"`) | | `fields` | `list[str]` | No | Fields to return | | `start_date` | `str` | No | Start date (YYYY-MM-DD) | | `end_date` | `str` | No | End date (YYYY-MM-DD) | | `force_latest` | `bool` | No | Force fresh data fetch | | `response_type` | `ResponseType` | No | Response mode | | `limit` | `int` | No | Max results (fast mode) | **Returns:** `PaginatedResult[TwitterPost]` ### get_retweets Get retweets of a specific post. ```python retweets = client.twitter.get_retweets("1234567890") ``` | Parameter | Type | Required | Description | | --- | --- | --- | --- | | `post_id` | `str` | Yes | Post ID | | `fields` | `list[str]` | No | Fields to return | | `start_date` | `str` | No | Start date (YYYY-MM-DD) | **Returns:** `PaginatedResult[TwitterPost]` ### get_comments Get replies to a specific post. ```python comments = client.twitter.get_comments("1234567890") ``` | Parameter | Type | Required | Description | | --- | --- | --- | --- | | `post_id` | `str` | Yes | Post ID | | `fields` | `list[str]` | No | Fields to return | | `start_date` | `str` | No | Start date (YYYY-MM-DD) | | `force_latest` | `bool` | No | Force fresh data fetch | **Returns:** `PaginatedResult[TwitterPost]` ### count_posts Count tweets containing a phrase within a date range. ```python count = client.twitter.count_posts("bitcoin", start_date="2025-01-01") print(f"{count:,} tweets mention bitcoin") ``` | Parameter | Type | Required | Description | | --- | --- | --- | --- | | `phrase` | `str` | Yes | Phrase to count | | `start_date` | `str` | No | Start date (YYYY-MM-DD) | | `end_date` | `str` | No | End date (YYYY-MM-DD) | **Returns:** `int` ### get_user Get a single Instagram user profile. ```python user = client.instagram.get_user("instagram") print(f"{user.full_name} — {user.follower_count:,} followers") ``` | Parameter | Type | Required | Description | | --- | --- | --- | --- | | `identifier` | `str` | Yes | Username or user ID | | `identifier_type` | `"username" \| "id"` | No | Identifier type (default: `"username"`) | | `fields` | `list[str]` | No | Fields to return | **Returns:** `InstagramUser` ### get_user_connections Get followers or following for an Instagram user. ```python followers = client.instagram.get_user_connections("instagram", "followers") ``` | Parameter | Type | Required | Description | | --- | --- | --- | --- | | `username` | `str` | Yes | Instagram username | | `connection_type` | `"followers" \| "following"` | Yes | Connection type | | `fields` | `list[str]` | No | Fields to return | | `force_latest` | `bool` | No | Force fresh data fetch | **Returns:** `PaginatedResult[InstagramUser]` ### get_posts_by_ids Get Instagram posts by their IDs. Post IDs must be in strong_id format: `"media_id_user_id"`. ```python posts = client.instagram.get_posts_by_ids(["3606450040306139062_4836333238"]) ``` | Parameter | Type | Required | Description | | --- | --- | --- | --- | | `post_ids` | `list[str]` | Yes | Array of post IDs in strong_id format | | `fields` | `list[str]` | No | Fields to return | | `force_latest` | `bool` | No | Force fresh data fetch | **Returns:** `list[InstagramPost]` ### search_posts Full-text search across Instagram posts. ```python results = client.instagram.search_posts("travel photography") ``` | Parameter | Type | Required | Description | | --- | --- | --- | --- | | `query` | `str` | Yes | Search query | | `fields` | `list[str]` | No | Fields to return | | `start_date` | `str` | No | Start date (YYYY-MM-DD) | | `end_date` | `str` | No | End date (YYYY-MM-DD) | | `force_latest` | `bool` | No | Force fresh data fetch | | `response_type` | `ResponseType` | No | Response mode | | `limit` | `int` | No | Max results (fast mode) | **Returns:** `PaginatedResult[InstagramPost]` ### get_post_interacting_users Get users who interacted with an Instagram post. ```python likers = client.instagram.get_post_interacting_users( "3606450040306139062_4836333238", "likers" ) ``` | Parameter | Type | Required | Description | | --- | --- | --- | --- | | `post_id` | `str` | Yes | Post ID (strong_id format) | | `interaction_type` | `"commenters" \| "likers"` | Yes | Interaction type | | `fields` | `list[str]` | No | Fields to return | | `force_latest` | `bool` | No | Force fresh data fetch | **Returns:** `PaginatedResult[InstagramUser]` ### get_user Get a single Reddit user profile. ```python user = client.reddit.get_user("spez") print(f"{user.username} — {user.total_karma:,} karma") ``` | Parameter | Type | Required | Description | | --- | --- | --- | --- | | `username` | `str` | Yes | Reddit username | | `fields` | `list[str]` | No | Fields to return | **Returns:** `RedditUser` ### get_users_by_keywords Find Reddit users who authored posts matching a keyword query. ```python users = client.reddit.get_users_by_keywords( '"machine learning"', subreddit="MachineLearning" ) ``` | Parameter | Type | Required | Description | | --- | --- | --- | --- | | `query` | `str` | Yes | Keyword query | | `fields` | `list[str]` | No | Fields to return | | `start_date` | `str` | No | Start date (YYYY-MM-DD) | | `end_date` | `str` | No | End date (YYYY-MM-DD) | | `subreddit` | `str` | No | Filter to subreddit | | `force_latest` | `bool` | No | Force fresh data fetch | **Returns:** `PaginatedResult[RedditUser]` ### get_post_with_comments Get a Reddit post with its comments. ```python result = client.reddit.get_post_with_comments("abc123") print(result.post.title) for comment in result.comments: print(f" {comment.author_username}: {comment.body[:80]}") ``` | Parameter | Type | Required | Description | | --- | --- | --- | --- | | `post_id` | `str` | Yes | Reddit post ID | | `post_fields` | `list[str]` | No | Post fields to return | | `comment_fields` | `list[str]` | No | Comment fields to return | | `force_latest` | `bool` | No | Force fresh data fetch | **Returns:** `RedditPostWithComments` The returned object contains: - `post` -- `RedditPost` - `comments` -- `list[RedditComment]` - `comments_pagination` -- `PaginationInfo | None` ### search_subreddits Search subreddits by name. ```python subs = client.reddit.search_subreddits("machine learning") top_five = client.reddit.search_subreddits("machine learning", limit=5) ``` | Parameter | Type | Required | Description | | --- | --- | --- | --- | | `query` | `str` | Yes | Subreddit name to search | | `limit` | `int` | No | Max results | | `fields` | `list[str]` | No | Fields to return | **Returns:** `list[RedditSubreddit]` ### get_subreddits_by_keywords Find subreddits related to a keyword query. ```python subs = client.reddit.get_subreddits_by_keywords("cryptocurrency") ``` | Parameter | Type | Required | Description | | --- | --- | --- | --- | | `query` | `str` | Yes | Keyword query | | `fields` | `list[str]` | No | Fields to return | | `start_date` | `str` | No | Start date (YYYY-MM-DD) | | `end_date` | `str` | No | End date (YYYY-MM-DD) | | `force_latest` | `bool` | No | Force fresh data fetch | **Returns:** `PaginatedResult[RedditSubreddit]` ### get_user Get a single TikTok user profile. ```python user = client.tiktok.get_user("charlidamelio") print(f"{user.nickname} — {user.follower_count:,} followers") # By numeric ID user = client.tiktok.get_user("123456789", identifier_type="id") ``` | Parameter | Type | Required | Description | | --- | --- | --- | --- | | `identifier` | `str` | Yes | Username or user ID | | `identifier_type` | `"username" \| "id"` | No | Identifier type (default: `"username"`) | | `fields` | `list[str]` | No | Fields to return | **Returns:** `TiktokUser` ### get_users_by_keywords Find TikTok users who authored posts matching a keyword query. ```python users = client.tiktok.get_users_by_keywords( '"machine learning"', response_type=ResponseType.FAST, limit=20, ) ``` | Parameter | Type | Required | Description | | --- | --- | --- | --- | | `query` | `str` | Yes | Keyword query | | `fields` | `list[str]` | No | Fields to return | | `start_date` | `str` | No | Start date (YYYY-MM-DD) | | `end_date` | `str` | No | End date (YYYY-MM-DD) | | `force_latest` | `bool` | No | Force fresh data fetch | | `response_type` | `ResponseType` | No | Response mode | | `limit` | `int` | No | Max results (fast mode) | **Returns:** `PaginatedResult[TiktokUser]` ### get_posts_by_user Get all posts by a TikTok user. ```python results = client.tiktok.get_posts_by_user("charlidamelio", start_date="2025-01-01") ``` | Parameter | Type | Required | Description | | --- | --- | --- | --- | | `identifier` | `str` | Yes | Username or user ID | | `identifier_type` | `"username" \| "id"` | No | Identifier type (default: `"username"`) | | `fields` | `list[str]` | No | Fields to return | | `start_date` | `str` | No | Start date (YYYY-MM-DD) | | `end_date` | `str` | No | End date (YYYY-MM-DD) | | `force_latest` | `bool` | No | Force fresh data fetch | | `response_type` | `ResponseType` | No | Response mode | | `limit` | `int` | No | Max results (fast mode) | **Returns:** `PaginatedResult[TiktokPost]` ### get_posts_by_hashtags Search TikTok posts by hashtags. Pass bare alphanumeric tags (no leading `#`). Max 5 hashtags per request; OR semantics across the list. ```python results = client.tiktok.get_posts_by_hashtags( ["dance", "fyp"], response_type=ResponseType.FAST, limit=50, ) ``` | Parameter | Type | Required | Description | | --- | --- | --- | --- | | `hashtags` | `list[str]` | Yes | Hashtags to search (max 5, no `#` prefix) | | `fields` | `list[str]` | No | Fields to return | | `start_date` | `str` | No | Start date (YYYY-MM-DD) | | `end_date` | `str` | No | End date (YYYY-MM-DD) | | `force_latest` | `bool` | No | Force fresh data fetch | | `response_type` | `ResponseType` | No | Response mode | | `limit` | `int` | No | Max results (fast mode) | **Returns:** `PaginatedResult[TiktokPost]` ### get_comments Get comments on a TikTok post. ```python comments = client.tiktok.get_comments("7123456789012345678") ``` | Parameter | Type | Required | Description | | --- | --- | --- | --- | | `post_id` | `str` | Yes | Post ID | | `fields` | `list[str]` | No | Fields to return | | `start_date` | `str` | No | Start date (YYYY-MM-DD) | | `end_date` | `str` | No | End date (YYYY-MM-DD) | | `force_latest` | `bool` | No | Force fresh data fetch | **Returns:** `PaginatedResult[TiktokComment]` --- # CLI Overview Source: https://docs.xpoz.ai/cli/overview The Xpoz CLI gives you direct access to social media intelligence from your terminal. Search users, posts, comments, and communities across four platforms -- no code required. ## Key Features Commands are auto-generated from the Xpoz Python SDK via reflection. When new tools are added to the platform, they appear in the CLI automatically. Twitter/X, Instagram, Reddit, and TikTok -- the same coverage as the MCP server and SDKs. Walk through paginated results with `--all-pages`, or jump to a specific page with `--page`. Get a CSV download URL for any search result with `--export-csv-url` -- ideal for bulk data collection. Native binaries for Linux (x86_64, arm64), macOS (Apple Silicon), and Windows (x86_64). Also available via pip, Homebrew, and winget. Structured JSON output by default, with a `--output pretty` option for human-readable formatting. ## Quick Example ```bash # Get a Twitter user profile xpoz-cli twitter get_user --identifier elonmusk # Search posts with boolean operators xpoz-cli twitter search_posts --query '"AI" AND ethics' --start-date 2025-01-01 --limit 20 # Export results as CSV xpoz-cli twitter search_posts --query bitcoin --export-csv-url ``` ## How It Works The CLI wraps the [Xpoz Python SDK](/sdks/python/quickstart), which connects to the [Xpoz MCP server](/mcp/overview). Every command maps directly to an MCP tool -- `twitter search_posts` calls the same `getTwitterPostsByKeywords` tool available through the MCP server and SDKs. ``` xpoz-cli twitter search_posts --query "AI" | v Xpoz Python SDK (xpoz) | v Xpoz MCP Server (mcp.xpoz.ai) | v Results (JSON / CSV) ``` ## Next Steps Install via script, Homebrew, pip, winget, or binary download. Platforms, global flags, pagination, and examples. Set up your access key and manage auth credentials. --- # Installation Source: https://docs.xpoz.ai/cli/installation ## Requirements - **Linux**: x86_64 or arm64 - **macOS**: Apple Silicon (M1+). Intel Macs should use the pip install method. - **Windows**: x86_64 - **Python**: 3.10+ (only required for pip install or build from source) ## Install **Linux / macOS** ```bash curl -fsSL https://raw.githubusercontent.com/XPOZpublic/xpoz-cli/main/install.sh | sh ``` The script auto-detects your OS and architecture, downloads the correct binary, verifies the SHA256 checksum, and installs to `~/.local/bin/xpoz-cli`. Override the install directory or pin a specific version: ```bash XPOZ_INSTALL_DIR=/usr/local/bin curl -fsSL https://raw.githubusercontent.com/XPOZpublic/xpoz-cli/main/install.sh | sh XPOZ_VERSION=1.2.0 curl -fsSL https://raw.githubusercontent.com/XPOZpublic/xpoz-cli/main/install.sh | sh ``` Ensure `~/.local/bin` is in your `PATH`. Add `export PATH="$HOME/.local/bin:$PATH"` to your shell profile if needed. --- **Windows (PowerShell)** ```powershell iwr -useb https://raw.githubusercontent.com/XPOZpublic/xpoz-cli/main/install.ps1 | iex ``` Installs to `%LOCALAPPDATA%\xpoz-cli\xpoz-cli.exe`. The script adds this directory to your user `PATH` automatically. Available on macOS and Linux: ```bash brew install XPOZpublic/xpoz/xpoz-cli ``` Or add the tap first, then install: ```bash brew tap XPOZpublic/xpoz brew install xpoz-cli ``` Update to the latest version: ```bash brew upgrade xpoz-cli ``` Works on any platform with Python 3.10+: ```bash pip install xpoz-cli ``` This is the recommended method for macOS Intel, which does not have a pre-built binary. Update to the latest version: ```bash pip install --upgrade xpoz-cli ``` Available on Windows: ```powershell winget install Xpoz.XpozCli ``` Update to the latest version: ```powershell winget upgrade Xpoz.XpozCli ``` Download the binary for your platform from [GitHub Releases](https://github.com/XPOZpublic/xpoz-cli/releases): | Platform | File | |---|---| | Linux x86_64 | `xpoz-cli-linux-amd64` | | Linux arm64 | `xpoz-cli-linux-arm64` | | macOS Apple Silicon | `xpoz-cli-macos-arm64` | | Windows x86_64 | `xpoz-cli-windows-amd64.exe` | Every release includes a `SHA256SUMS` file. Verify the download: ```bash sha256sum -c SHA256SUMS --ignore-missing ``` Make the binary executable and move it to your PATH: ```bash chmod +x xpoz-cli-linux-amd64 mv xpoz-cli-linux-amd64 ~/.local/bin/xpoz-cli ``` macOS Intel is not available as a pre-built binary. Use `pip install xpoz-cli` instead. Requires Python 3.10+ and pip: ```bash pip install xpoz pyinstaller pyinstaller --onefile --name xpoz-cli xpoz_cli.py ``` The compiled binary will be in the `dist/` directory. ## Verify Installation ```bash xpoz-cli --version ``` ## Next Steps Log in with your access key to start making queries. Learn about platforms, commands, and global flags. --- # Usage Source: https://docs.xpoz.ai/cli/usage ## Platform Subcommands The CLI organizes commands by platform. Each platform exposes the same tools available through the [MCP server](/mcp/tools/overview) and [SDKs](/sdks/typescript/quickstart). | Subcommand | Platform | Example tools | |---|---|---| | `twitter` | Twitter/X | `get_user`, `search_posts`, `get_post_comments`, `get_user_connections` | | `instagram` | Instagram | `get_user`, `search_posts`, `get_post_comments`, `search_users` | | `reddit` | Reddit | `get_user`, `search_posts`, `search_comments`, `get_subreddit` | | `tiktok` | TikTok | `get_user`, `search_posts`, `get_posts_by_hashtags`, `get_post_comments` | | `tracking` | Cross-platform | `add_tracked_items`, `get_tracked_items`, `remove_tracked_items` | Commands are dynamically generated from the [Python SDK](/sdks/python/quickstart) via reflection. When new tools are added to the platform, they appear in the CLI automatically. ## Command Discovery Use `--help` at any level to explore available commands and parameters: ```bash # List all platforms xpoz-cli --help # List commands for a platform xpoz-cli twitter --help # Show parameters for a specific command xpoz-cli twitter search_posts --help ``` ## Global Flags These flags work with any command: | Flag | Environment Variable | Default | Description | |---|---|---|---| | `--api-key KEY` | `XPOZ_API_KEY` | Stored config | Override the stored access key | | `--server-url URL` | `XPOZ_SERVER_URL` | `https://mcp.xpoz.ai/mcp` | Custom MCP server endpoint | | `--output json\|pretty` | -- | `json` | Output format | | `--all-pages` | -- | Off | Automatically walk through all pages | | `--max-pages N` | -- | -- | Safety cap when using `--all-pages` | | `--page N` | -- | -- | Jump to a specific page | | `--export-csv-url` | -- | Off | Return a CSV download URL instead of rows | | `--timeout SECS` | -- | `300` | Operation timeout in seconds | ## Examples ### Twitter ```bash # Look up a user profile xpoz-cli twitter get_user --identifier elonmusk # Search posts with boolean operators and date range xpoz-cli twitter search_posts --query '"AI" AND ethics' --start-date 2025-01-01 --limit 20 # Get replies to a post xpoz-cli twitter get_post_comments --post-id 1234567890 ``` ### Instagram ```bash # Look up a user profile xpoz-cli instagram get_user --identifier natgeo # Search posts by keyword xpoz-cli instagram search_posts --query "street photography" --limit 10 ``` ### Reddit ```bash # Search posts in a specific subreddit, sorted by top of the month xpoz-cli reddit search_posts --query "python tutorial" --subreddit learnpython --sort top --time month # Paginate through all results xpoz-cli reddit search_posts --query "python tutorial" --subreddit learnpython --all-pages ``` ### TikTok ```bash # Look up a user profile xpoz-cli tiktok get_user --identifier charlidamelio # Search posts by hashtag xpoz-cli tiktok get_posts_by_hashtags --hashtags "cooking,recipe" --limit 20 ``` ### Tracking ```bash # Add a keyword to track across platforms xpoz-cli tracking add_tracked_items --keywords "artificial intelligence" # List all tracked items xpoz-cli tracking get_tracked_items ``` ## Output Formatting By default, the CLI outputs raw JSON. Use `--output pretty` for human-readable formatting: ```bash xpoz-cli twitter get_user --identifier elonmusk ``` ```json {"id":"123","username":"elonmusk","name":"Elon Musk","followersCount":200000000} ``` ```bash xpoz-cli twitter get_user --identifier elonmusk --output pretty ``` ```json { "id": "123", "username": "elonmusk", "name": "Elon Musk", "followersCount": 200000000 } ``` Pipe JSON output to `jq` for advanced filtering and transformation: `xpoz-cli twitter search_posts --query "AI" | jq '.data[].text'` ## Pagination Search commands return paginated results (100 items per page). You have three options for navigating pages: | Strategy | Flag | Use case | |---|---|---| | Walk all pages | `--all-pages` | Collect the full result set | | Capped walk | `--all-pages --max-pages 5` | Collect up to N pages as a safety limit | | Jump to page | `--page 3` | Resume or inspect a specific page | ```bash # Get all pages of results xpoz-cli reddit search_posts --query "machine learning" --all-pages # Limit to 10 pages max xpoz-cli reddit search_posts --query "machine learning" --all-pages --max-pages 10 # Jump directly to page 5 xpoz-cli reddit search_posts --query "machine learning" --page 5 ``` When using `--all-pages` on broad queries, set `--max-pages` to avoid unexpectedly large result sets. Each page consumes one call. ## CSV Export Use `--export-csv-url` to get a download URL for the full result set as a CSV file, hosted on S3. This is useful for bulk data collection and analysis in spreadsheet tools. ```bash xpoz-cli twitter search_posts --query bitcoin --export-csv-url ``` The command returns a URL instead of JSON rows. The CSV file includes all fields and all matching results. For more details on CSV exports, see the [CSV Exports guide](/guides/csv-exports). ## Next Steps Manage your access key and auth credentials. Write effective search queries with boolean operators and phrases. --- # Authentication Source: https://docs.xpoz.ai/cli/authentication The CLI requires an access key to authenticate with the Xpoz MCP server. Get your key from the [Xpoz dashboard](https://www.xpoz.ai/settings). **Start instantly — no account needed.** Generate a free token and use it as your API key: ```bash TOKEN=$(curl -s -X POST https://api.xpoz.ai/api/trial/token -H "Content-Type: application/json" -d '{"source":""}' | jq -r .data.accessKey) export XPOZ_API_KEY=$TOKEN xpoz-cli twitter get_user --identifier elonmusk ``` This returns a preview of up to 5 results per call. To get full data, pagination, and CSV export, [create a free account](https://xpoz.ai/get-token) — no credit card required. ## Login Sign up or log in at [xpoz.ai](https://xpoz.ai) and copy your access key from the [Settings page](https://www.xpoz.ai/settings). ```bash xpoz-cli auth login ``` You will be prompted to enter your access key. The key is stored locally in a config file (see [Config File Location](#config-file-location) below). ```bash xpoz-cli auth status ``` Confirms that a valid access key is stored and shows your account status. ## Logout Remove the stored access key: ```bash xpoz-cli auth logout ``` ## Auth Commands | Command | Description | |---|---| | `xpoz-cli auth login` | Store your access key | | `xpoz-cli auth status` | Check authentication status | | `xpoz-cli auth logout` | Remove stored credentials | ## Credential Precedence The CLI resolves credentials in this order: 1. **`--api-key` flag** -- highest priority, overrides everything 2. **`XPOZ_API_KEY` environment variable** -- useful for CI/CD and scripting 3. **Stored config file** -- set by `xpoz-cli auth login` ```bash # Use a specific key for one command xpoz-cli twitter get_user --identifier elonmusk --api-key sk-your-key # Or set the environment variable export XPOZ_API_KEY=sk-your-key xpoz-cli twitter get_user --identifier elonmusk ``` For CI/CD pipelines and automation, use the `XPOZ_API_KEY` environment variable. For local development, `auth login` is more convenient. ## Config File Location ``` ~/.config/xpoz/config.json ``` The file is created with `0600` permissions (owner read/write only) to protect your access key. ``` %APPDATA%\xpoz\config.json ``` The config file contains your access key in plain text. Do not commit it to version control. The CLI sets restrictive file permissions (`0600`) on Linux and macOS to prevent other users on the system from reading it. ## Next Steps Start querying platforms with the CLI. Set up the same access key with the MCP server directly. --- # Agent Skills Source: https://docs.xpoz.ai/skills/overview ## What are Agent Skills? Agent Skills are pre-written instructions that teach AI agents how to perform specific tasks correctly. They package domain expertise into a format that any compatible agent can absorb — so the agent knows the right tools to use, the right order to use them, and the right way to interpret results. Xpoz provides skills for specific social media intelligence tasks like sentiment analysis, influencer discovery, and data export, as well as general best practices for using Xpoz effectively. ## Available Skills | Skill | Description | Platforms | |---|---|---| | Best Practices | Reference guide for Xpoz query syntax, response modes, and patterns | All | | Getting Started | Onboarding guide for setup, auth, and capability discovery | All | | Social Tracking | Set up continuous tracking for better coverage and fresher data | All | | Sentiment Analyzer | Analyze brand/topic sentiment with scoring and theme extraction | Twitter, Reddit, Instagram | | Twitter Data Export | Export up to 500K rows of Twitter data to CSV | Twitter | | Influencer Discovery | Find and rank influencers by engagement, reach, and authenticity | Twitter | | Reddit Research | Deep-dive into Reddit discussions for market research | Reddit | | Competitive Intelligence | Compare 2-5 brands across social media metrics | Twitter, Reddit | | Security OSINT | Monitor for CVEs, breaches, and emerging threats | Twitter, Reddit | ## Compatible Agents - Claude Code (recommended) - OpenAI Codex CLI - Cursor - Gemini CLI - ChatGPT (via custom instructions) - Any agent supporting the SKILL.md standard ## Setup Install all Xpoz skills with a single command: ```bash npx skills add XPOZpublic/xpoz-agent-skills --all ``` Or install a specific skill: ```bash npx skills add XPOZpublic/xpoz-agent-skills --skill social-sentiment-analyzer ``` This works with Claude Code, Cursor, Codex, Gemini, and [15+ other agents](https://www.skills.sh/). Skills are installed directly into your agent's skills directory — no further configuration needed. **Available skill names:** `xpoz-best-practices`, `xpoz-getting-started`, `xpoz-social-tracking`, `social-sentiment-analyzer`, `twitter-data-export`, `influencer-discovery`, `reddit-research`, `competitive-intel`, `security-osint` You still need to configure Xpoz access (MCP server or access key) to use the skills. See the [MCP Installation](/mcp/installation) or [Authentication](/authentication) guide. ## Explore Skills Reference guide for Xpoz query syntax, response modes, and patterns. Onboarding guide for setup, auth, and capability discovery. Set up continuous tracking for better coverage and fresher data. Analyze brand/topic sentiment with scoring and theme extraction. Export up to 500K rows of Twitter data to CSV. Find and rank influencers by engagement, reach, and authenticity. Deep-dive into Reddit discussions for market research. Compare 2-5 brands across social media metrics. Monitor for CVEs, breaches, and emerging threats. --- # Best Practices Source: https://docs.xpoz.ai/skills/best-practices The Best Practices skill is a reference guide that should be loaded for any Xpoz interaction. It covers authentication, query construction, response mode selection, field optimization, and common workflow patterns across all 48 Xpoz tools. ## Query Syntax Reference for building effective queries across all Xpoz search tools. - **Simple keywords**: `artificial intelligence` (matches posts containing both words) - **Exact phrases**: `"machine learning"` (matches the exact phrase) - **AND operator**: `AI AND healthcare` (both terms required) - **OR operator**: `ChatGPT OR "Claude AI"` (either term matches) - **Grouping**: `("generative AI" OR LLM) AND startup` - **Date filtering**: Use `startDate` and `endDate` parameters in YYYY-MM-DD format ## Response Modes Every search tool supports a `responseType` parameter that controls how results are delivered. | Mode | Description | Best For | | --- | --- | --- | | `fast` | Returns results immediately in a single response | Quick lookups, small datasets, interactive analysis | | `paging` | Returns paginated results (100 per page) with cursor-based navigation | Medium datasets, iterative analysis, when you need to process results page by page | | `csv` | Exports results to S3 as a CSV file (up to 500K rows) | Bulk exports, large datasets, data pipeline ingestion | ## Field Selection Use the `fields` parameter to request only specific fields, reducing response size and improving performance. Rather than returning the full object with all available fields, specify exactly which fields you need. ```json { "keywords": "artificial intelligence", "fields": ["id", "text", "authorUsername", "likeCount"], "responseType": "fast" } ``` ```json { "keywords": "artificial intelligence", "responseType": "fast" } ``` Returns all available fields, which may include dozens of properties you do not need. ## Continuous Tracking Continuous tracking monitors keywords, users, subreddits, and hashtags on a regular schedule, resulting in better data coverage and fresher results. Track any brand, keyword, or user you query regularly to ensure more complete, up-to-date content. See the [Social Tracking skill](/skills/social-tracking) for setup details on adding and managing tracked items. ## Common Workflow Patterns Search for posts using keyword queries, analyze results in-agent to identify patterns or insights, then export the full dataset to CSV for downstream processing. Search for relevant users by keyword or criteria, fetch their recent posts, then perform engagement or content analysis across the collected data. Set up tracking for keywords or users, let data accumulate over days or weeks, then run periodic analysis and reporting on the growing dataset. ## Troubleshooting | Issue | Cause | Solution | | --- | --- | --- | | No results returned | Query too narrow or date range too restrictive | Broaden keywords, extend date range, try OR instead of AND | | Slow response | Large result set with responseType="fast" | Switch to "paging" mode or narrow the query | | CSV export pending | Export still processing | Poll `checkOperationStatus` with the operation ID until complete | | Authentication error | Invalid or expired access key | Regenerate your key at xpoz.ai or re-authenticate via OAuth | | Rate limit hit | Too many requests per minute | Add delays between requests, batch queries where possible | ## Platform Quick Reference - **Twitter/X**: 13 tools (users, posts, connections, comments) - **Instagram**: 9 tools (users, posts, comments, connections) - **Reddit**: 9 tools (users, posts, comments, subreddits) - **TikTok**: 9 tools (users, posts, comments, hashtags) - **Operations**: 2 tools - **Account**: 1 tool - **Auth**: 2 tools - **Tracking**: 3 tools Total: 48 tools. See [MCP Tools Overview](/mcp/tools/overview) for the full reference. --- # Getting Started Source: https://docs.xpoz.ai/skills/getting-started The Getting Started skill guides you through setting up Xpoz with your preferred integration, verifying your account, and discovering what you can do. Follow the steps below to get up and running. ## Choose Your Integration For Claude Code, add the Xpoz MCP server to `~/.claude.json`: ```json { "mcpServers": { "xpoz": { "url": "https://mcp.xpoz.ai/mcp", "transport": "http-stream" } } } ``` OAuth authentication happens automatically on first use. ```bash pip install xpoz export XPOZ_API_KEY=your-key-here ``` ```bash npm install @xpoz/xpoz export XPOZ_API_KEY=your-key-here ``` ```bash brew install xpoz-ai/tap/xpoz-cli xpoz-cli auth login ``` Get a free access key at [xpoz.ai/get-token](https://xpoz.ai/get-token). ## Verify Your Setup Run `checkAccessKeyStatus` to confirm your key is valid and see your current usage. Run `getAccountDetails` to see your plan, remaining quota, and tracked items. Try a simple search like "Search Twitter for posts about AI agents" to confirm everything works end-to-end. ## Set Up Tracking Tracking gives you fresher data by continuously collecting results for your keywords, users, and hashtags. We recommend starting by tracking your brand name and key competitors. See [Social Tracking](/skills/social-tracking) for full details on how to configure and manage tracked items. ## Skill Routing | If you want to... | Use this skill | | ------------------------------------------ | ----------------------------------------------------------- | | Analyze sentiment around a brand or topic | [Sentiment Analyzer](/skills/sentiment-analyzer) | | Export Twitter data to CSV | [Twitter Data Export](/skills/twitter-data-export) | | Find influencers in a niche | [Influencer Discovery](/skills/influencer-discovery) | | Research what Reddit thinks about something | [Reddit Research](/skills/reddit-research) | | Compare brands head-to-head | [Competitive Intelligence](/skills/competitive-intel) | | Monitor security threats and CVEs | [Security OSINT](/skills/security-osint) | | Learn query syntax and best practices | [Best Practices](/skills/best-practices) | | Track keywords, users, or hashtags | [Social Tracking](/skills/social-tracking) | ## Next Steps --- # Social Tracking Source: https://docs.xpoz.ai/skills/social-tracking The Social Tracking skill manages continuous tracking across all four platforms. Tracked items are monitored regularly by Xpoz, resulting in better data coverage and fresher results. ## Why use continuous tracking? - **Better coverage**: Regular monitoring captures more posts and updates, so your results are more complete. - **Fresher data**: Tracked items are kept up to date, so you always get the most recent content. ## Supported Types | Platform | Keyword | User | Subreddit | Hashtag | | ----------- | ------- | ---- | --------- | ------- | | Twitter/X | Yes | Yes | - | - | | Instagram | Yes | Yes | - | - | | Reddit | Yes | Yes | Yes | - | | TikTok | Yes | Yes | - | Yes | ## Xpoz Tools Used | Tool | Purpose | | -------------------- | ------------------------------- | | `getTrackedItems` | List all currently tracked items | | `addTrackedItems` | Add new items to track | | `removeTrackedItems` | Stop tracking items | ## Common Workflows ### Track your brand across all platforms Add your brand name as a keyword on Twitter, Instagram, Reddit, and TikTok. Add your official accounts as tracked users on each platform. Add any relevant subreddits where your brand is discussed. ### Monitor a competitor Track the competitor's brand name as a keyword across platforms. Track their official social media accounts. Periodically run the [Competitive Intelligence](/skills/competitive-intel) skill to compare metrics. ### TikTok hashtag campaign Track the campaign hashtag on TikTok. Track related keywords to capture posts that mention the campaign without the hashtag. Monitor post volume and engagement over time. ### Subreddit monitoring Track the subreddit by name on Reddit. Track relevant keywords to capture cross-subreddit discussions. Use the [Reddit Research](/skills/reddit-research) skill for periodic analysis. ## Get Started Get a free access key at [xpoz.ai/get-token](https://xpoz.ai/get-token). See the [installation guide](/skills/overview#installation) to add this skill to your agent. --- # Sentiment Analyzer Source: https://docs.xpoz.ai/skills/sentiment-analyzer The Sentiment Analyzer skill searches Twitter, Reddit, and Instagram for posts about a brand or topic, classifies each post by sentiment, extracts recurring themes, and produces a scored summary. It handles multi-platform data collection and analysis in a single workflow. ## Example Prompts - "What's the sentiment around Tesla on social media?" - "How are people feeling about Cursor IDE on Reddit?" - "Analyze public sentiment about the new iPhone launch" - "What do people think about remote work policies?" ## How It Works Queries Twitter, Reddit, and Instagram using the target brand or topic as keywords. Each post is classified into one of five levels: positive, leaning-positive, neutral, leaning-negative, or negative. Identifies 5-8 recurring themes across the collected posts (e.g., pricing concerns, feature praise, competitor comparisons). Produces a structured report with an overall sentiment score, platform breakdown, key themes, and notable posts. ## Xpoz Tools Used | Tool | Purpose | | --- | --- | | `getTwitterPostsByKeywords` | Search Twitter for relevant posts | | `getRedditPostsByKeywords` | Search Reddit for relevant discussions | | `getInstagramPostsByKeywords` | Search Instagram for relevant content | ## Output Format - **Overall Sentiment Score**: 0-100 scale (0 = extremely negative, 100 = extremely positive) - **Platform Breakdown**: Per-platform sentiment scores and post counts in a table - **Key Themes**: 5-8 recurring themes with sentiment tendency and representative quotes - **Notable Posts**: High-engagement posts that exemplify the dominant sentiment - **Summary**: Concise narrative of findings and actionable insights ## Get Started Get a free access key at [xpoz.ai/get-token](https://xpoz.ai/get-token). See the [installation guide](/skills/overview#installation) to add this skill to your agent. --- # Twitter Data Export Source: https://docs.xpoz.ai/skills/twitter-data-export The Twitter Data Export skill handles bulk data extraction from Twitter/X. It supports keyword-based search, author-based search, date filtering, and boolean query syntax. Results are exported as CSV files with up to 500K rows per export. ## Example Prompts - "Export tweets about Claude Code to CSV" - "Download @OpenAI tweets from January 2026" - "Export all tweets mentioning 'artificial intelligence' AND 'healthcare' to CSV" - "Get a CSV of tweets from @elonmusk in the last 30 days" ## Available Fields | Field | Description | | --- | --- | | `id` | Tweet unique identifier | | `text` | Full tweet text | | `authorUsername` | Author's Twitter handle | | `authorId` | Author's unique identifier | | `createdAtDate` | Publication date | | `likeCount` | Number of likes | | `retweetCount` | Number of retweets | | `quoteCount` | Number of quote tweets | | `impressionCount` | Number of impressions | | `replyCount` | Number of replies | | `language` | Tweet language code | | `isRetweet` | Whether this is a retweet | | `isReply` | Whether this is a reply | ## How It Works Constructs a search query using keywords, boolean operators, date ranges, or author filters. Calls Xpoz tools with `responseType="csv"` for bulk export or standard mode for smaller datasets. For large exports, monitors the async operation via `checkOperationStatus` until the CSV file is ready. Returns the CSV download link or displays results inline for smaller datasets. ## Xpoz Tools Used | Tool | Purpose | | --- | --- | | `getTwitterPostsByKeywords` | Search Twitter posts by keyword query | | `getTwitterPostsByAuthor` | Get posts from a specific Twitter user | | `checkOperationStatus` | Monitor async CSV export progress | ## Query Syntax Boolean operators let you build precise queries: | Syntax | Example | | --- | --- | | Simple | `artificial intelligence` | | Phrase | `"machine learning"` | | AND | `AI AND healthcare` | | OR | `ChatGPT OR "Claude AI"` | | Combined | `("generative AI" OR LLM) AND startup` | ## Get Started Get a free access key at [xpoz.ai/get-token](https://xpoz.ai/get-token). See the [installation guide](/skills/overview#installation) to add this skill to your agent. --- # Influencer Discovery Source: https://docs.xpoz.ai/skills/influencer-discovery The Influencer Discovery skill finds and ranks influencers in any niche on Twitter/X. It evaluates candidates across engagement, reach, relevance, authenticity, and consistency, then categorizes them by tier and voice type. ## Example Prompts - "Find top 20 AI agent influencers on Twitter" - "Find micro-influencers for sustainable fashion" - "Who are the most influential voices in cybersecurity on Twitter?" - "Discover crypto influencers with high engagement and low bot probability" ## Scoring Formula | Factor | Weight | Description | | --- | --- | --- | | Relevance | 30% | How closely the influencer's content matches the target niche | | Engagement | 30% | Like, retweet, and reply rates relative to follower count | | Reach | 20% | Follower count and impression volume | | Authenticity | 10% | Bot probability score (lower is better, via `isInauthenticProbScore`) | | Consistency | 10% | Regular posting cadence in the target niche | ## Influencer Tiers | Tier | Follower Range | | --- | --- | | Mega | 1M+ | | Macro | 100K - 1M | | Micro | 10K - 100K | | Nano | 1K - 10K | ## Voice Types Each influencer is classified into a voice type based on their content style: - **Analyst**: Data-driven commentary and research - **Builder**: Hands-on creators sharing their work - **Educator**: Teaching and explaining concepts - **News**: Breaking news and industry updates - **Commentator**: Opinion and thought leadership - **Community**: Community building and curation ## Xpoz Tools Used | Tool | Purpose | | --- | --- | | `getTwitterUsersByKeywords` | Find users relevant to the niche (returns `relevantTweetsCount`, `relevantTweetsLikesSum`, `relevantTweetsImpressionsSum`, `isInauthenticProbScore`) | | `getTwitterPostsByAuthor` | Analyze recent posts from candidate influencers | ## Get Started Get a free access key at [xpoz.ai/get-token](https://xpoz.ai/get-token). See the [installation guide](/skills/overview#installation) to add this skill to your agent. --- # Reddit Research Source: https://docs.xpoz.ai/skills/reddit-research The Reddit Research skill performs deep analysis of Reddit discussions around a topic or product. It maps subreddit distribution, analyzes sentiment from voting patterns, extracts recurring themes, and identifies key community voices. ## Example Prompts - "What does Reddit think about Cursor IDE?" - "Reddit market research: indie hacker automation tools" - "Analyze Reddit discussions about electric vehicles in 2026" - "What are the top complaints about Notion on Reddit?" ## Analysis Methodology Searches Reddit posts and comments matching the target query across all relevant subreddits. Identifies which subreddits discuss the topic most and how discussion varies by community. Uses upvote/downvote ratios and comment engagement (score/comments ratio) as sentiment proxies. Categorizes discussions into theme groups and surfaces representative quotes. Produces a structured report with subreddit distribution, themes, sentiment, and key users. ## Theme Categories The skill extracts and categorizes themes into: - **Pain Points**: Problems, frustrations, and feature requests - **Praise**: Positive experiences and standout features - **Comparisons**: How the topic is compared to alternatives - **Use Cases**: Real-world applications and workflows - **Questions**: Common questions and knowledge gaps ## Xpoz Tools Used | Tool | Purpose | | --- | --- | | `getRedditPostsByKeywords` | Search Reddit posts by keyword query | | `getRedditUsersByKeywords` | Find active Reddit users in the topic space | ## Get Started Get a free access key at [xpoz.ai/get-token](https://xpoz.ai/get-token). See the [installation guide](/skills/overview#installation) to add this skill to your agent. --- # Competitive Intelligence Source: https://docs.xpoz.ai/skills/competitive-intel The Competitive Intelligence skill compares 2-5 brands head-to-head across social media. It calculates share of voice, compares sentiment, measures engagement differences, identifies audience overlap, and maps competitive positioning. ## Example Prompts - "Compare Slack vs Discord vs Teams on social media" - "How does Claude compare to ChatGPT and Gemini?" - "Competitive analysis: Figma vs Sketch vs Adobe XD" - "Compare sentiment around Nike vs Adidas vs Puma" ## Analysis Components - **Share of Voice**: Percentage of total social mentions each brand captures across platforms. Measured by total post volume per brand. - **Sentiment Comparison**: Side-by-side sentiment scores for each brand, highlighting which brand has the most positive (or negative) perception. - **Engagement Comparison**: Average likes, retweets, comments per post for each brand, showing which brand generates the most interaction. - **Audience Overlap**: Identifies users who discuss multiple brands, revealing shared audience segments. - **Positioning Analysis**: How each brand is perceived relative to competitors -- what unique strengths and weaknesses the social conversation reveals. ## How It Works Constructs targeted queries for each brand with disambiguation terms to avoid false positives. Searches Twitter and Reddit for each brand independently. Normalizes engagement and volume metrics across brands for fair comparison. Calculates share of voice, sentiment deltas, and engagement ratios. Produces a comparative report with tables, rankings, and positioning insights. ## Xpoz Tools Used | Tool | Purpose | | --- | --- | | `getTwitterPostsByKeywords` | Search Twitter mentions per brand | | `getTwitterUsersByKeywords` | Find users discussing each brand | | `getRedditPostsByKeywords` | Search Reddit discussions per brand | ## Get Started Get a free access key at [xpoz.ai/get-token](https://xpoz.ai/get-token). See the [installation guide](/skills/overview#installation) to add this skill to your agent. --- # Security OSINT Source: https://docs.xpoz.ai/skills/security-osint The Security OSINT skill monitors Twitter and Reddit for security-related discussions including CVE mentions, zero-day chatter, data breach reports, exploit code sharing, and emerging threats. It reconstructs timelines, assesses severity from social signals, and evaluates source credibility. ## Example Prompts - "What's the security community saying about CVE-2026-1234?" - "OSINT: find breach reports about Company X" - "Monitor Twitter for zero-day exploit discussions this week" - "What are the emerging security threats being discussed on Reddit?" - "Track threat actor mentions for APT29 on social media" ## Capabilities - **CVE Tracking**: Search for specific CVE IDs across social platforms to gauge community response, severity perception, and exploitation status. - **Breach Monitoring**: Detect and aggregate reports of data breaches, leaked credentials, and security incidents as they surface on social media. - **Exploit Chatter**: Identify discussions about proof-of-concept exploits, attack techniques, and vulnerability details. - **Timeline Reconstruction**: Build chronological timelines of security events from the earliest social mentions to current status. - **Severity Assessment**: Gauge real-world severity based on social signals -- discussion volume, expert engagement, and community urgency. - **Source Credibility**: Evaluate the credibility of threat intelligence sources based on their posting history and community standing. ## How It Works Constructs targeted queries using CVE IDs, vulnerability terms, breach terminology, and threat actor names. Queries Twitter and Reddit, focusing on security-focused communities and researchers. Assesses severity, identifies key sources, and reconstructs event timelines. Produces a structured report with timeline, severity assessment, source credibility, and recommended actions. ## Xpoz Tools Used | Tool | Purpose | | --- | --- | | `getTwitterPostsByKeywords` | Search Twitter for security-related posts | | `getTwitterUsersByKeywords` | Identify security researchers and threat intel sources | | `getRedditPostsByKeywords` | Search Reddit security communities (r/netsec, r/cybersecurity, etc.) | ## Get Started Get a free access key at [xpoz.ai/get-token](https://xpoz.ai/get-token). See the [installation guide](/skills/overview#installation) to add this skill to your agent. --- # Integrations Source: https://docs.xpoz.ai/integrations/overview All Xpoz integrations connect to the same hosted MCP server at `https://mcp.xpoz.ai/mcp`. Choose the client that fits your workflow -- every integration gives you access to the full set of [48 MCP tools](/mcp/tools/overview) across Twitter/X, Instagram, Reddit, and TikTok. ## Available Integrations One-command setup via `claude mcp add`. Supports bearer token and OAuth authentication. Add Xpoz to your Gemini CLI settings file with bearer token auth. Official plugin with MCP tools, slash commands, and auto-discovered skills for the Cursor IDE. Configure the Xpoz MCP server in the Codex CLI for agentic social media research. npm package for building AI apps with social media tools using generateText, streamText, and agents. Python package for building LangChain agents with social media intelligence tools. Python package that gives CrewAI agent crews social media intelligence tools. Python package with Xpoz tool specs for LlamaIndex agents. Connect n8n AI agent workflows to Xpoz with the built-in MCP Client Tool node. ## Common Setup Pattern Every integration follows the same pattern: 1. **Get your access key** at [xpoz.ai/get-token](https://xpoz.ai/get-token) 2. **Configure the MCP server** URL (`https://mcp.xpoz.ai/mcp`) with a bearer token header 3. **Start querying** -- your client discovers all 48 tools automatically For details on authentication methods (access key, OAuth 2.1, token-based), see the [Authentication](/authentication) page. ## Next Steps Learn about the MCP server architecture and capabilities Browse all 48 tools across 4 platforms Pre-built AI workflows for common research tasks --- # Claude (Web) Source: https://docs.xpoz.ai/integrations/claude-web Claude on claude.ai connects to the Xpoz MCP server as a custom connector. Once added, Claude can search live social media data across Twitter/X, Instagram, Reddit, and TikTok with all [48 tools](/mcp/tools/overview), in any conversation where you enable it. ## Setup Go to **Customize > Connectors** on [claude.ai](https://claude.ai). Click **+**, then **Add custom connector**, and set the URL to: ``` https://mcp.xpoz.ai/mcp ``` Click **Add**. Sign in with your Google account when prompted, or use your Xpoz access key from the [Get Token](https://xpoz.ai/get-token) page. In a conversation, click the **+** button at the lower left of the chat box, choose **Connectors**, and turn on Xpoz. Ask: ``` Search Twitter for posts about "artificial intelligence" from the last week ``` If Claude calls `getTwitterPostsByKeywords` and returns results, the connection is working. ## Setup notes - Connectors are tied to your Claude account: a connector added here is also available in [Claude Desktop](/integrations/claude-desktop), [Claude Cowork](/integrations/claude-cowork), and the mobile apps. - Custom connectors are available on Free, Pro, Max, Team, and Enterprise plans; the Free plan is limited to one custom connector. - On Team and Enterprise plans, an owner adds the connector under **Organization settings > Connectors**; members then connect it from **Customize > Connectors**. ## What you can ask - "What is Reddit saying about my brand today?" - "Find the most-liked tweets about our product launch this week" - "Which TikTok creators posted about skincare in the last 48 hours?" ## Next Steps Browse all 48 tools across 4 platforms Write effective search queries with boolean operators --- # Claude Desktop Source: https://docs.xpoz.ai/integrations/claude-desktop Claude Desktop connects to the Xpoz MCP server as a custom connector, the same account-level connector used by claude.ai. Once added, Claude can search live social media data across Twitter/X, Instagram, Reddit, and TikTok with all [48 tools](/mcp/tools/overview). ## Setup In Claude Desktop, go to **Settings > Connectors**. Click **Add custom connector** and set the URL to: ``` https://mcp.xpoz.ai/mcp ``` Click **Add**. Sign in with your Google account when prompted, or use your Xpoz access key from the [Get Token](https://xpoz.ai/get-token) page. Start a new conversation and ask: ``` Search Twitter for posts about "artificial intelligence" from the last week ``` If Claude calls `getTwitterPostsByKeywords` and returns results, the connection is working. ## Setup notes - Connectors are tied to your Claude account: a connector added on claude.ai or in Cowork appears here automatically, and vice versa. If you already added Xpoz in [Claude (Web)](/integrations/claude-web), there is nothing to configure. - The connection to the Xpoz server is brokered through your Claude account from Anthropic's infrastructure, not from your machine, so no local install, Node.js, or config file is required. - Custom connectors are available on Free, Pro, Max, Team, and Enterprise plans; the Free plan is limited to one custom connector. ## What you can ask - "Summarize the top complaints about our product on Reddit this month" - "Compare engagement on our last 10 tweets with our main competitor's" - "Find Instagram posts mentioning our brand with the highest engagement this week" ## Next Steps Browse all 48 tools across 4 platforms Monitor keywords and accounts continuously --- # Claude Cowork Source: https://docs.xpoz.ai/integrations/claude-cowork Claude Cowork uses the same account-level custom connectors as claude.ai and Claude Desktop. Adding the Xpoz MCP server once makes live social media data across Twitter/X, Instagram, Reddit, and TikTok available to your Cowork sessions with all [48 tools](/mcp/tools/overview). ## Setup Go to **Customize > Connectors** (in Cowork or on claude.ai; they share the same connector list). Click **+**, then **Add custom connector**, and set the URL to: ``` https://mcp.xpoz.ai/mcp ``` Click **Add**. Sign in with your Google account when prompted, or use your Xpoz access key from the [Get Token](https://xpoz.ai/get-token) page. In a Cowork session, ask: ``` What are people saying about our brand on Reddit and Twitter today? ``` If the agent calls Xpoz tools and returns posts, the connection is working. ## Setup notes - Connectors are tied to your Claude account and shared across claude.ai, Claude Desktop, Cowork, and the mobile apps; add Xpoz once and every surface has it. - Custom connectors are available on Free, Pro, Max, Team, and Enterprise plans; the Free plan is limited to one custom connector. - On Team and Enterprise plans, an owner adds the connector under **Organization settings > Connectors**; members then connect it from **Customize > Connectors**. - Long-running Cowork tasks pair well with [continuous tracking](/tracking): tracked keywords and accounts give agents fresher, deeper coverage. ## What you can ask - "Run a weekly digest: mentions of our brand across all four platforms, sorted by risk" - "Build a report on the top 20 creators posting about our category this month" - "Watch r/oursubreddit and summarize new complaint threads each morning" ## Next Steps Browse all 48 tools across 4 platforms Pre-built social media research workflows --- # Claude Code Source: https://docs.xpoz.ai/integrations/claude-code Claude Code connects to the Xpoz MCP server over HTTP, giving you access to all [48 tools](/mcp/tools/overview) directly from your terminal. Bearer token auth is the fastest path; OAuth is also supported for interactive workflows. ## Setup Sign up at [xpoz.ai](https://xpoz.ai) and copy your access key from the [Get Token](https://xpoz.ai/get-token) page. Run a single command: ```bash claude mcp add xpoz-mcp https://mcp.xpoz.ai/mcp \ -t http \ -H "Authorization: Bearer YOUR_API_KEY" ``` This registers the Xpoz MCP server with Claude Code. All 48 tools are discovered automatically on the next conversation. Start a new Claude Code session and ask: ``` Search Twitter for posts about "artificial intelligence" from the last week ``` If Claude calls `getTwitterPostsByKeywords` and returns results, the connection is working. ## Alternative: Manual Configuration Instead of the CLI command, you can add the server directly to your `~/.claude.json` configuration file: ```json { "mcpServers": { "xpoz-mcp": { "url": "https://mcp.xpoz.ai/mcp", "type": "http", "headers": { "Authorization": "Bearer YOUR_API_KEY" } } } } ``` Restart Claude Code after editing the configuration file. ## OAuth Authentication If you prefer OAuth over a static bearer token, add the server without an authorization header: ```bash claude mcp add xpoz-mcp https://mcp.xpoz.ai/mcp -t http ``` Claude Code will initiate the OAuth 2.1 flow automatically when it first connects to the server. You authenticate with your Google account, and subsequent requests are handled with the issued JWT token. OAuth requires the Xpoz MCP server to have Google OAuth enabled. See the [Authentication](/authentication) page for details on configuring OAuth 2.1 with Google SSO. ## What You Can Do Once connected, ask Claude to perform any social media research task: - Search posts by keyword across Twitter, Instagram, Reddit, and TikTok - Look up user profiles and follower counts - Analyze engagement metrics and trends - Track keywords and users for continuous monitoring - Export large datasets in CSV format See the full list of available tools in the [MCP Tools reference](/mcp/tools/overview), or explore pre-built research workflows in [Agent Skills](/skills/overview). ## Next Steps Browse all 48 tools across 4 platforms Write effective search queries with boolean operators --- # ChatGPT Source: https://docs.xpoz.ai/integrations/chatgpt ChatGPT connects to the Xpoz MCP server through developer mode connectors. Once added, ChatGPT can search live social media data across Twitter/X, Instagram, Reddit, and TikTok with all [48 tools](/mcp/tools/overview) in conversations where the connector is enabled. ## Setup Open **Settings > Connectors**, and under **Advanced** turn on **Developer mode**. Back in **Settings > Connectors**, click **Create** and configure: | Field | Value | |---|---| | **Name** | `Xpoz` | | **MCP server URL** | `https://mcp.xpoz.ai/mcp` | Complete authentication (sign in with Google, or use your Xpoz access key from the [Get Token](https://xpoz.ai/get-token) page), confirm the trust prompt, and click **Create**. In a new conversation, open the **+** menu, choose **Developer mode**, and enable the Xpoz connector. Connectors are enabled per conversation. Ask: ``` Search Twitter for posts about "artificial intelligence" from the last week ``` If ChatGPT calls `getTwitterPostsByKeywords` and returns results, the connection is working. ## Setup notes - Developer mode is available on paid ChatGPT plans; see [OpenAI's developer mode guide](https://help.openai.com/en/articles/12584461-developer-mode-and-mcp-apps-in-chatgpt) for current plan availability. - The connector must be enabled in each conversation where you want to use it (the **+** menu > **Developer mode**). - Without developer mode, ChatGPT only accepts connectors that implement its deep-research interface; the full Xpoz toolset requires developer mode. ## What you can ask - "Summarize the top complaints about [brand] on Twitter and Reddit this week" - "Find Instagram posts mentioning [product] with the highest engagement this month" - "Which subreddits are discussing our product category the most right now?" ## Next Steps Browse all 48 tools across 4 platforms Write effective search queries with boolean operators --- # OpenAI Codex Source: https://docs.xpoz.ai/integrations/codex The OpenAI Codex CLI supports MCP servers for tool integration. Add the Xpoz MCP server to give Codex access to all [48 tools](/mcp/tools/overview) across Twitter/X, Instagram, Reddit, and TikTok. ## Setup Sign up at [xpoz.ai](https://xpoz.ai) and copy your access key from the [Get Token](https://xpoz.ai/get-token) page. Add the Xpoz server to your Codex MCP configuration file at `~/.codex/config.json`: ```json { "mcpServers": { "xpoz": { "url": "https://mcp.xpoz.ai/mcp", "headers": { "Authorization": "Bearer YOUR_API_KEY" } } } } ``` Replace `YOUR_API_KEY` with your actual Xpoz access key. Close and reopen the Codex CLI to load the new configuration. All 48 Xpoz tools will be discovered automatically. Ask Codex to run a test query: ``` Search Twitter for posts about "machine learning" using Xpoz ``` If Codex calls `getTwitterPostsByKeywords` and returns results, the connection is working. ## Alternative: Environment Variable You can also pass the access key as an environment variable when launching Codex: ```bash XPOZ_ACCESS_TOKEN=YOUR_API_KEY codex ``` This requires the MCP server entry in your config to reference the environment variable instead of a hardcoded token. ## What You Can Do With Xpoz connected, Codex can: - Search posts and users across all four platforms - Retrieve engagement metrics and follower data - Track keywords and users for continuous monitoring - Export large result sets in CSV format See the full list of available tools in the [MCP Tools reference](/mcp/tools/overview). ## Next Steps Browse all 48 tools across 4 platforms Get started with Xpoz in under 2 minutes --- # Gemini CLI Source: https://docs.xpoz.ai/integrations/gemini-cli Gemini CLI supports MCP servers natively. Add the Xpoz MCP server to your settings file to access all [48 tools](/mcp/tools/overview) from the Gemini CLI. ## Setup Sign up at [xpoz.ai](https://xpoz.ai) and copy your access key from the [Get Token](https://xpoz.ai/get-token) page. Add the Xpoz server to your Gemini CLI settings file at `~/.gemini/settings.json`: ```json { "mcpServers": { "xpoz": { "uri": "https://mcp.xpoz.ai/mcp", "headers": { "Authorization": "Bearer YOUR_API_KEY" } } } } ``` Replace `YOUR_API_KEY` with your actual Xpoz access key. If the file already contains other MCP servers, add the `"xpoz"` entry inside the existing `"mcpServers"` object. Close and reopen Gemini CLI to pick up the new configuration. The 48 Xpoz tools will be available in your next session. Ask Gemini to run a query: ``` Look up the Twitter user @elonmusk using Xpoz ``` If Gemini calls `getTwitterUser` and returns profile data, the connection is working. ## Example Queries Once connected, you can ask Gemini to perform social media research: ``` Search Reddit for posts about "rust programming" in the learnrust subreddit ``` ``` Find the top Instagram posts mentioning "sustainable fashion" this month ``` ``` Get TikTok user profile for @charlidamelio ``` Gemini will call the appropriate Xpoz MCP tools and return structured results. ## Next Steps Browse all 48 tools across 4 platforms Learn about fast, paging, and CSV response modes --- # Cursor Source: https://docs.xpoz.ai/integrations/cursor Cursor supports MCP servers natively, and Xpoz ships an official Cursor plugin that bundles the MCP server configuration with slash commands and auto-discovered skills. Install the plugin for the full experience, or add the MCP server directly to your Cursor settings for tools only. Either way you get access to all [48 tools](/mcp/tools/overview) across Twitter/X, Instagram, Reddit, and TikTok. ## Setup with the Plugin Sign up at [xpoz.ai](https://xpoz.ai) and copy your access key from the [Get Token](https://xpoz.ai/get-token) page. Install the official Xpoz plugin from [cursor.directory/plugins/xpoz](https://cursor.directory/plugins/xpoz). The plugin includes the MCP server configuration, three slash commands, and three skills. The plugin reads your token from the `XPOZ_ACCESS_TOKEN` environment variable. Alternatively, configure the server directly in your Cursor MCP settings (`~/.cursor/mcp.json` or Cursor Settings, then MCP): ```json { "mcpServers": { "xpoz": { "url": "https://mcp.xpoz.ai/mcp", "headers": { "Authorization": "Bearer YOUR_API_KEY" } } } } ``` Replace `YOUR_API_KEY` with your actual Xpoz access key. Run `/xpoz-setup` in Cursor to verify your connection, or ask directly: ``` Search Twitter for posts about "artificial intelligence" from the last week ``` If Cursor calls `getTwitterPostsByKeywords` and returns results, the connection is working. ## Commands The plugin adds three slash commands: | Command | Description | | ---------------------- | ------------------------------------------------------------ | | `/xpoz-setup` | Configure the MCP connection and verify your account | | `/xpoz-track` | Manage tracked keywords, users, subreddits, and hashtags | | `/xpoz-best-practices` | Reference docs for query syntax, pagination, field selection | ## Skills Skills are auto-discovered by Cursor and activate based on context: | Skill | When It Activates | | ------------------------ | ------------------------------------------------------------------------------- | | **xpoz-getting-started** | Setting up Xpoz, checking account status, first-time onboarding | | **xpoz-social-tracking** | Adding or removing tracked items, monitoring brands, social listening | | **xpoz-best-practices** | Any Xpoz tool usage: query syntax, pagination, field selection, troubleshooting | ## MCP Server Only If you prefer to skip the plugin, add the server configuration from step 3 above to `~/.cursor/mcp.json` on its own. Cursor discovers all 48 tools automatically; you only miss the bundled commands and skills. ## What You Can Do Once connected, ask Cursor to perform any social media research task: - Search posts by keyword across Twitter, Instagram, Reddit, and TikTok - Look up user profiles, followers, and connections - Analyze engagement metrics and trends - Track keywords, users, subreddits, and hashtags for continuous monitoring - Export large datasets in CSV format ## Next Steps Browse all 48 tools across 4 platforms Write effective search queries with boolean operators --- # Vercel AI SDK Source: https://docs.xpoz.ai/integrations/vercel-ai-sdk The [`@xpoz/ai-sdk`](https://www.npmjs.com/package/@xpoz/ai-sdk) package provides 44 ready-made tools for the [Vercel AI SDK](https://sdk.vercel.ai). Use them with `generateText`, `streamText`, or any AI SDK-compatible framework to give your AI agent access to Twitter/X, Instagram, Reddit, and TikTok data. ## Setup Sign up at [xpoz.ai](https://xpoz.ai) and copy your access key from the [Get Token](https://xpoz.ai/get-token) page. ```bash npm install @xpoz/ai-sdk ai zod ``` You also need an AI provider. For example, with Anthropic: ```bash npm install @ai-sdk/anthropic ``` ```bash export XPOZ_API_KEY=your-access-key ``` ```typescript import { generateText, stepCountIs } from "ai"; import { anthropic } from "@ai-sdk/anthropic"; import { xpozTools } from "@xpoz/ai-sdk"; const result = await generateText({ model: anthropic("claude-sonnet-4-6"), tools: xpozTools(), stopWhen: stepCountIs(3), prompt: "What are people saying about AI agents on Twitter?", }); console.log(result.text); ``` The AI model automatically discovers all 44 tools and decides which ones to call based on the prompt. ## Using Individual Tools If you only need specific tools, import them directly instead of the full bundle: ```typescript import { xpozTwitterSearch, xpozInstagramUser } from "@xpoz/ai-sdk"; const result = await generateText({ model: anthropic("claude-sonnet-4-6"), tools: { twitterSearch: xpozTwitterSearch(), instagramUser: xpozInstagramUser(), }, prompt: "Look up the NASA Instagram profile", }); ``` ## Field Selection Every tool supports an optional `fields` parameter to control which fields are returned. Each tool's description lists all available fields for that entity type. ```typescript import { xpozTwitterUser } from "@xpoz/ai-sdk"; const tool = xpozTwitterUser(); const user = await tool.execute( { identifier: "elonmusk", fields: ["username", "followersCount", "description"] }, { toolCallId: "demo", messages: [] } ); ``` Field names differ across platforms. For example, Twitter uses `followersCount` while Instagram and TikTok use `followerCount`. Each tool's description lists the correct field names. ## TypeScript Types The package exports response types for all entity types: ```typescript import { type TwitterUser, type TwitterPost, type InstagramUser, type InstagramPost, type RedditUser, type RedditPost, type TiktokUser, type TiktokPost, } from "@xpoz/ai-sdk"; ``` All tools also define an `outputSchema` for typed results via the AI SDK's `TypedToolResult` system. ## Available Tools ### Twitter/X | Tool | Description | |------|-------------| | `xpozTwitterSearch` | Search posts by keywords, hashtags, or phrases | | `xpozTwitterUser` | Get a user profile by username or ID | | `xpozTwitterUserPosts` | Get posts by a specific user | | `xpozTwitterPostComments` | Get replies on a post | | `xpozTwitterSearchUsers` | Search users by name | | `xpozTwitterUserConnections` | Get a user's followers or following | | `xpozTwitterUsersByKeywords` | Find users who posted about a topic | | `xpozTwitterCountPosts` | Count posts matching a phrase | | `xpozTwitterPostsByIds` | Get specific posts by their IDs | | `xpozTwitterPostRetweets` | Get retweets of a post | | `xpozTwitterPostQuotes` | Get quote tweets of a post | | `xpozTwitterPostInteractingUsers` | Get users who liked, retweeted, or quoted a post | | `xpozTwitterUsers` | Get multiple user profiles by usernames or IDs | ### Instagram | Tool | Description | |------|-------------| | `xpozInstagramSearch` | Search posts by keywords | | `xpozInstagramUser` | Get a user profile by username or ID | | `xpozInstagramUserPosts` | Get posts by a specific user | | `xpozInstagramPostComments` | Get comments on a post | | `xpozInstagramSearchUsers` | Search users by name | | `xpozInstagramUsersByKeywords` | Find users who posted about a topic | | `xpozInstagramPostsByIds` | Get specific posts by their IDs | | `xpozInstagramUserConnections` | Get a user's followers or following | | `xpozInstagramPostInteractingUsers` | Get users who liked or commented on a post | ### Reddit | Tool | Description | |------|-------------| | `xpozRedditSearch` | Search posts by keywords | | `xpozRedditUser` | Get a user profile | | `xpozRedditPostWithComments` | Get a post with its comment thread | | `xpozRedditSearchComments` | Search comments by keywords | | `xpozRedditSearchSubreddits` | Search subreddits by name or topic | | `xpozRedditSubreddit` | Get a subreddit's info and recent posts | | `xpozRedditUsersByKeywords` | Find users who posted about a topic | | `xpozRedditSearchUsers` | Search users by name | | `xpozRedditSubredditsByKeywords` | Find subreddits related to a topic | ### TikTok | Tool | Description | |------|-------------| | `xpozTiktokSearch` | Search videos by keywords | | `xpozTiktokUser` | Get a creator profile by username or ID | | `xpozTiktokUserPosts` | Get videos by a specific creator | | `xpozTiktokPostComments` | Get comments on a video | | `xpozTiktokSearchUsers` | Search creators by name | | `xpozTiktokPostsByHashtags` | Search videos by hashtags | | `xpozTiktokUsersByKeywords` | Find creators who posted about a topic | | `xpozTiktokPostsByIds` | Get specific videos by their IDs | | `xpozTiktokUsersByHashtags` | Find creators who posted with specific hashtags | ### Tracking & Account | Tool | Description | |------|-------------| | `xpozGetTrackedItems` | List all tracked keywords, users, and hashtags | | `xpozAddTrackedItems` | Add items to track across platforms | | `xpozRemoveTrackedItems` | Stop tracking items | | `xpozAccountDetails` | Get account plan, usage, and billing info | ## Configuration All tools accept an optional configuration object: ```typescript import { xpozTools } from "@xpoz/ai-sdk"; const tools = xpozTools({ apiKey: "your-access-key", // defaults to XPOZ_API_KEY env var serverUrl: "https://mcp.xpoz.ai/mcp", // default timeoutMs: 300000, // default: 5 minutes }); ``` ## What You Can Do - Search posts by keyword across Twitter, Instagram, Reddit, and TikTok - Look up user profiles and follower counts - Analyze engagement metrics and trends - Track keywords and users for continuous monitoring - Build AI agents that autonomously research social media topics ## Next Steps Browse all 48 tools across 4 platforms View the package on npm --- # LangChain Source: https://docs.xpoz.ai/integrations/langchain The [`langchain-xpoz`](https://pypi.org/project/langchain-xpoz/) Python package provides 44 LangChain tools for social media intelligence. Use them with any LangChain-compatible model to give your AI agent access to Twitter/X, Instagram, Reddit, and TikTok data. ## Setup Sign up at [xpoz.ai](https://xpoz.ai) and copy your access key from the [Get Token](https://xpoz.ai/get-token) page. ```bash pip install langchain-xpoz ``` You also need a model provider. For example, with Anthropic: ```bash pip install langchain-anthropic ``` ```bash export XPOZ_API_KEY=your-access-key ``` ```python from langchain_xpoz import XpozTwitterSearch, XpozInstagramUser, XpozRedditSearch from langchain_anthropic import ChatAnthropic from langchain.agents import create_tool_calling_agent, AgentExecutor from langchain_core.prompts import ChatPromptTemplate tools = [ XpozTwitterSearch(), XpozInstagramUser(), XpozRedditSearch(), ] llm = ChatAnthropic(model="claude-sonnet-4-6") prompt = ChatPromptTemplate.from_messages([ ("system", "You are a social media research assistant."), ("human", "{input}"), ("placeholder", "{agent_scratchpad}"), ]) agent = create_tool_calling_agent(llm=llm, tools=tools, prompt=prompt) executor = AgentExecutor(agent=agent, tools=tools) result = executor.invoke({ "input": "What are people saying about AI agents on Twitter?" }) print(result["output"]) ``` ## Using Individual Tools You can also use tools directly without an agent: ```python from langchain_xpoz import XpozTwitterSearch tool = XpozTwitterSearch() result = tool.invoke({"query": "AI agents", "max_results": 5}) print(result) ``` Or pass `api_key` explicitly instead of using the environment variable: ```python tool = XpozTwitterSearch(api_key="your-access-key") ``` ## Available Tools ### Twitter/X | Tool | Description | |------|-------------| | `XpozTwitterSearch` | Search posts by keywords, hashtags, or phrases | | `XpozTwitterUser` | Get a user profile by username or ID | | `XpozTwitterUserPosts` | Get posts by a specific user | | `XpozTwitterPostComments` | Get replies on a post | | `XpozTwitterSearchUsers` | Search users by name | | `XpozTwitterUserConnections` | Get a user's followers or following | | `XpozTwitterUsersByKeywords` | Find users who posted about a topic | | `XpozTwitterCountPosts` | Count posts matching a phrase | | `XpozTwitterPostsByIds` | Get specific posts by their IDs | | `XpozTwitterPostRetweets` | Get retweets of a post | | `XpozTwitterPostQuotes` | Get quote tweets of a post | | `XpozTwitterPostInteractingUsers` | Get users who retweeted, quoted, or commented on a post | | `XpozTwitterUsers` | Get multiple user profiles by usernames or IDs | ### Instagram | Tool | Description | |------|-------------| | `XpozInstagramSearch` | Search posts by keywords | | `XpozInstagramUser` | Get a user profile by username or ID | | `XpozInstagramUserPosts` | Get posts by a specific user | | `XpozInstagramPostComments` | Get comments on a post | | `XpozInstagramSearchUsers` | Search users by name | | `XpozInstagramUsersByKeywords` | Find users who posted about a topic | | `XpozInstagramPostsByIds` | Get specific posts by their IDs | | `XpozInstagramUserConnections` | Get a user's followers or following | | `XpozInstagramPostInteractingUsers` | Get users who liked or commented on a post | ### Reddit | Tool | Description | |------|-------------| | `XpozRedditSearch` | Search posts by keywords | | `XpozRedditUser` | Get a user profile | | `XpozRedditPostWithComments` | Get a post with its comment thread | | `XpozRedditSearchComments` | Search comments by keywords | | `XpozRedditSearchSubreddits` | Search subreddits by name or topic | | `XpozRedditSubreddit` | Get a subreddit's info and recent posts | | `XpozRedditUsersByKeywords` | Find users who posted about a topic | | `XpozRedditSearchUsers` | Search users by name | | `XpozRedditSubredditsByKeywords` | Find subreddits related to a topic | ### TikTok | Tool | Description | |------|-------------| | `XpozTiktokSearch` | Search videos by keywords | | `XpozTiktokUser` | Get a creator profile by username or ID | | `XpozTiktokUserPosts` | Get videos by a specific creator | | `XpozTiktokPostComments` | Get comments on a video | | `XpozTiktokSearchUsers` | Search creators by name | | `XpozTiktokPostsByHashtags` | Search videos by hashtags | | `XpozTiktokUsersByKeywords` | Find creators who posted about a topic | | `XpozTiktokPostsByIds` | Get specific videos by their IDs | | `XpozTiktokUsersByHashtags` | Find creators who posted with specific hashtags | ### Tracking & Account | Tool | Description | |------|-------------| | `XpozGetTrackedItems` | List all tracked keywords, users, and hashtags | | `XpozAddTrackedItems` | Add items to track across platforms | | `XpozRemoveTrackedItems` | Stop tracking items | | `XpozAccountDetails` | Get account plan, usage, and billing info | ## Configuration All tools accept an optional `api_key` parameter. If not provided, the `XPOZ_API_KEY` environment variable is used: ```python from langchain_xpoz import XpozTwitterSearch # Using environment variable (recommended) tool = XpozTwitterSearch() # Passing API key explicitly tool = XpozTwitterSearch(api_key="your-access-key") ``` ## What You Can Do - Search posts by keyword across Twitter, Instagram, Reddit, and TikTok - Look up user profiles and follower counts - Analyze engagement metrics and trends - Track keywords and users for continuous monitoring - Build AI agents that autonomously research social media topics ## Next Steps Browse all 48 tools across 4 platforms View the package on PyPI --- # CrewAI Source: https://docs.xpoz.ai/integrations/crewai The [`crewai-xpoz`](https://pypi.org/project/crewai-xpoz/) Python package provides 44 CrewAI tools for social media intelligence. Add them to any agent in your crew to give it access to Twitter/X, Instagram, Reddit, and TikTok data. ## Setup Sign up at [xpoz.ai](https://xpoz.ai) and copy your access key from the [Get Token](https://xpoz.ai/get-token) page. ```bash pip install crewai-xpoz ``` You also need an LLM provider for your agents. For example, with Anthropic: ```bash pip install "crewai[anthropic]" ``` ```bash export XPOZ_API_KEY=your-access-key ``` ```python from crewai import Agent, Crew, Task from crewai_xpoz import XpozTwitterSearch, XpozRedditSearch researcher = Agent( role="Social media researcher", goal="Answer questions using real social media data", backstory="You research social media using the tools provided.", tools=[XpozTwitterSearch(), XpozRedditSearch()], llm="anthropic/claude-sonnet-4-6", ) task = Task( description="Find recent posts about 'AI agents' on Twitter and summarize the main themes.", expected_output="A short summary grounded in real posts.", agent=researcher, ) crew = Crew(agents=[researcher], tasks=[task]) result = crew.kickoff() print(result) ``` ## Using Individual Tools You can also call tools directly without a crew: ```python from crewai_xpoz import XpozTwitterSearch tool = XpozTwitterSearch() result = tool.run(query="AI agents", limit=5) print(result) ``` When a task needs the most recent posts, tell the agent to omit date filters. Tools accept optional date-range parameters, and models sometimes fill them speculatively, which skews results older. ## Available Tools ### Twitter/X | Tool | Description | |------|-------------| | `XpozTwitterSearch` | Search posts by keywords, hashtags, or phrases | | `XpozTwitterUser` | Get a user profile by username or ID | | `XpozTwitterUserPosts` | Get posts by a specific user | | `XpozTwitterPostComments` | Get replies on a post | | `XpozTwitterSearchUsers` | Search users by name | | `XpozTwitterUserConnections` | Get a user's followers or following | | `XpozTwitterUsersByKeywords` | Find users who posted about a topic | | `XpozTwitterCountPosts` | Count posts matching a phrase | | `XpozTwitterPostsByIds` | Get specific posts by their IDs | | `XpozTwitterPostRetweets` | Get retweets of a post | | `XpozTwitterPostQuotes` | Get quote tweets of a post | | `XpozTwitterPostInteractingUsers` | Get users who retweeted, quoted, or commented on a post | | `XpozTwitterUsers` | Get multiple user profiles by usernames or IDs | ### Instagram | Tool | Description | |------|-------------| | `XpozInstagramSearch` | Search posts by keywords | | `XpozInstagramUser` | Get a user profile by username or ID | | `XpozInstagramUserPosts` | Get posts by a specific user | | `XpozInstagramPostComments` | Get comments on a post | | `XpozInstagramSearchUsers` | Search users by name | | `XpozInstagramUsersByKeywords` | Find users who posted about a topic | | `XpozInstagramPostsByIds` | Get specific posts by their IDs | | `XpozInstagramUserConnections` | Get a user's followers or following | | `XpozInstagramPostInteractingUsers` | Get users who liked or commented on a post | ### Reddit | Tool | Description | |------|-------------| | `XpozRedditSearch` | Search posts by keywords | | `XpozRedditUser` | Get a user profile | | `XpozRedditPostWithComments` | Get a post with its comment thread | | `XpozRedditSearchComments` | Search comments by keywords | | `XpozRedditSearchSubreddits` | Search subreddits by name or topic | | `XpozRedditSubreddit` | Get a subreddit's info and recent posts | | `XpozRedditUsersByKeywords` | Find users who posted about a topic | | `XpozRedditSearchUsers` | Search users by name | | `XpozRedditSubredditsByKeywords` | Find subreddits related to a topic | ### TikTok | Tool | Description | |------|-------------| | `XpozTiktokSearch` | Search videos by keywords | | `XpozTiktokUser` | Get a creator profile by username or ID | | `XpozTiktokUserPosts` | Get videos by a specific creator | | `XpozTiktokPostComments` | Get comments on a video | | `XpozTiktokSearchUsers` | Search creators by name | | `XpozTiktokPostsByHashtags` | Search videos by hashtags | | `XpozTiktokUsersByKeywords` | Find creators who posted about a topic | | `XpozTiktokPostsByIds` | Get specific videos by their IDs | | `XpozTiktokUsersByHashtags` | Find creators who posted with specific hashtags | ### Tracking & Account | Tool | Description | |------|-------------| | `XpozGetTrackedItems` | List all tracked keywords, users, and hashtags | | `XpozAddTrackedItems` | Add items to track across platforms | | `XpozRemoveTrackedItems` | Stop tracking items | | `XpozAccountDetails` | Get account plan, usage, and billing info | ## Configuration All tools accept an optional `api_key` parameter. If not provided, the `XPOZ_API_KEY` environment variable is used: ```python from crewai_xpoz import XpozTwitterSearch # Using environment variable (recommended) tool = XpozTwitterSearch() # Passing API key explicitly tool = XpozTwitterSearch(api_key="your-access-key") ``` ## What You Can Do - Give research agents in a crew live access to posts across Twitter, Instagram, Reddit, and TikTok - Look up user profiles, followers, and engagement metrics mid-task - Split platforms across specialist agents and combine their findings - Track keywords and users for continuous monitoring - Build crews that autonomously research brands, competitors, and trends ## Next Steps Browse all 48 tools across 4 platforms View the package on PyPI --- # LlamaIndex Source: https://docs.xpoz.ai/integrations/llamaindex The [`llama-index-tools-xpoz`](https://pypi.org/project/llama-index-tools-xpoz/) Python package provides five Xpoz tool specs (32 tools) for LlamaIndex agents: search and analyze Twitter/X, Instagram, Reddit, and TikTok data with no social media API keys required. ## Setup Sign up at [xpoz.ai](https://xpoz.ai) and copy your access key from the [Get Token](https://xpoz.ai/get-token) page. ```bash pip install llama-index-tools-xpoz ``` You also need LlamaIndex and an LLM provider, for example: ```bash pip install llama-index llama-index-llms-openai ``` ```bash export XPOZ_API_KEY=your-access-key ``` ```python from llama_index.core.agent.workflow import FunctionAgent from llama_index.llms.openai import OpenAI from llama_index.tools.xpoz import XpozTwitterToolSpec, XpozRedditToolSpec tools = XpozTwitterToolSpec().to_tool_list() + XpozRedditToolSpec().to_tool_list() agent = FunctionAgent( tools=tools, llm=OpenAI(model="gpt-5.4"), system_prompt="You are a social media research assistant. Use the Xpoz tools for data.", ) response = await agent.run( "What are people saying about AI agents on Twitter and Reddit?" ) print(response) ``` ## Using Individual Tools Call spec methods directly without an agent: ```python from llama_index.tools.xpoz import XpozTwitterToolSpec spec = XpozTwitterToolSpec() result = spec.search_twitter_posts("AI agents", limit=5) ``` Pass `api_key` explicitly instead of using the environment variable: `XpozTwitterToolSpec(api_key="your-access-key")`. When a task needs the most recent posts, tell the agent to omit date filters. Tools accept optional date-range parameters, and models sometimes fill them speculatively, which skews results older. ## Tool Specs | Spec | Tools | | --- | --- | | `XpozTwitterToolSpec` | search posts, user profile, user posts, post comments, search users, followers/following, users by keywords, count posts | | `XpozInstagramToolSpec` | search posts, user profile, user posts, post comments, search users, users by keywords | | `XpozRedditToolSpec` | search posts, post with comments, search comments, user profile, search subreddits, subreddit with posts, subreddits by keywords | | `XpozTiktokToolSpec` | search videos, videos by hashtags, creator profile, creator videos, video comments, search creators, creators by hashtags | | `XpozTrackingToolSpec` | list/add/remove tracked items, account details | Give an agent only the specs it needs; a smaller tool list helps the model choose correctly. ## What You Can Do - Build research agents that ground answers in live posts across four platforms - Look up user profiles, followers, and engagement metrics mid-task - Track keywords and users for continuous monitoring (`XpozTrackingToolSpec`) - Combine with your indexes: retrieve internal docs and live social data in one agent ## Next Steps Browse all 48 tools across 4 platforms View the package on PyPI --- # n8n Source: https://docs.xpoz.ai/integrations/n8n n8n's built-in **MCP Client Tool** node connects any AI Agent workflow to the Xpoz MCP server, giving your agents live access to Twitter/X, Instagram, Reddit, and TikTok data. No custom node installation required. ## Setup Sign up at [xpoz.ai](https://xpoz.ai) and copy your access key from the [Get Token](https://xpoz.ai/get-token) page. Create a workflow with an **AI Agent** node (for example, triggered by **When chat message received**) and attach a chat model to it. Add the **MCP Client Tool** node as a tool of the AI Agent and configure it: - **Server Transport**: HTTP Streamable - **Endpoint**: `https://mcp.xpoz.ai/mcp` - **Authentication**: Bearer Auth, with your Xpoz access key as the token - **Tools to Include**: All (or select specific tools; see the tip below) Ask the agent something that needs social media data, for example: "What are people saying about our brand on Reddit this week?" The agent discovers the Xpoz tools automatically and calls them as needed. Xpoz exposes 48 tools. If your workflow only needs one platform, use **Tools to Include → Selected** and pick the relevant tools (for example `getTwitterPostsByKeywords` and `getTwitterUser`). A smaller tool list helps the model choose correctly and keeps prompts shorter. ## Example workflows - **Brand monitoring digest**: Schedule Trigger → AI Agent ("summarize the last day of posts mentioning our brand across Twitter and Reddit") with the Xpoz MCP tool → email or Slack node with the summary. - **Lead research**: Chat Trigger → AI Agent that looks up a prospect's Twitter/Instagram profile and recent posts before a sales call. - **Competitor tracking**: Schedule Trigger → AI Agent using tracked keywords (`getTrackedItems`, `addTrackedItems`) to maintain continuous coverage, then post changes to a channel. ## Notes - The MCP Client Tool node requires a recent n8n version; the HTTP Streamable transport is the current recommended option (SSE is legacy). - Long-running Xpoz operations return an `operationId`; agents can poll with `checkOperationStatus`. For most searches the default fast mode returns results directly. - Each tool call consumes Xpoz credits per your plan. ## Next Steps Browse all 48 tools across 4 platforms Get better search results with boolean operators and filters