Claude Skill

xpoz-best-practices

Reference guide for using Xpoz effectively. Load this skill whenever working with Xpoz MCP tools, SDKs, or CLI — it ensures correct query syntax, optimal field selection, proper pagination, and best practices for every Xpoz interaction. Covers authentication, query syntax (boolea

LLM Mart · 0 points · 3 views 0 listing impressions 0 install-command copies
Virus-scanned Reviewed automatically before listing.

Full trust report

Download xpozpublic-xpoz-agent-skills-skills_xpoz-best-practices-d18bc4b.zip · 27 KB
Part of xpozpublic/xpoz-agent-skills — 13 skills

Install

skills CLI npx skills add https://github.com/XPOZpublic/xpoz-agent-skills/tree/main/skills/xpoz-best-practices
Claude Code claude plugin marketplace add https://llmmart.ai/marketplace.json && claude plugin install xpozpublic-xpoz-agent-skills@llmmart
Git git clone https://github.com/XPOZpublic/xpoz-agent-skills.git

The skills CLI installs just this skill, for any of its supported agents. Claude Code installs the whole xpozpublic/xpoz-agent-skills collection as a plugin from our marketplace. Git is the plain clone.

Skill manifest

Xpoz Best Practices

Overview

Xpoz is a social media intelligence platform providing access to Twitter/X, Instagram, Reddit, and TikTok data through MCP tools, Python SDK, TypeScript SDK, and CLI — no social media API keys required.

When to Use

Load this skill for any Xpoz interaction — not just when the user explicitly asks about best practices. It provides the context needed to use Xpoz tools correctly:

  • Calling any Xpoz MCP tool (query syntax, field selection, response modes)
  • Writing code with the Python or TypeScript SDK
  • Using the Xpoz CLI
  • Setting up authentication or tracking
  • Troubleshooting errors or empty results
  • Choosing which tool to use for a specific task

Quick Start

MCP — add the Xpoz MCP server to your agent's config. The server URL is https://mcp.xpoz.ai/mcp. Most MCP clients handle OAuth automatically on first tool call.

Example for Claude Code (~/.claude.json):

{
  "mcpServers": {
    "xpoz": {
      "url": "https://mcp.xpoz.ai/mcp",
      "transport": "streamable-http"
    }
  }
}

Python SDK:

pip install xpoz
from xpoz import XpozClient
client = XpozClient()  # reads XPOZ_API_KEY env var
results = client.twitter.search_posts("artificial intelligence")
print(f"Found {results.pagination.total_rows:,} tweets")
client.close()

TypeScript SDK:

npm install @xpoz/xpoz
import { XpozClient } from "@xpoz/xpoz";
const client = new XpozClient();
await client.connect();
const results = await client.twitter.searchPosts("artificial intelligence");
console.log(`Found ${results.pagination.totalRows.toLocaleString()} tweets`);
await client.close();

CLI:

pip install xpoz-cli
xpoz-cli twitter search_posts --query "artificial intelligence" --limit 20

See references/authentication.md for detailed auth flows (MCP, SDK, CLI). See references/sdk.md for complete Python & TypeScript SDK reference. See references/cli.md for CLI installation, commands, and rendering modes.

Query Syntax

All keyword search tools support boolean query syntax:

Operator Example Effect
Exact phrase "machine learning" Matches exact phrase
OR "AI" OR "artificial intelligence" Matches either term
AND "Tesla" AND "earnings" Matches both terms
Grouping ("deep learning" OR "neural network") AND python Combines operators

Date filtering: Use startDate / endDate in YYYY-MM-DD format. Omit to use defaults (varies by tool).

Content filtering (Twitter only): Set filterOutRetweets: true to exclude retweets.

Forbidden in query string: from:, to:, lang:, since:, until:, filter: — use dedicated parameters instead.

Platform Quick Reference

Twitter/X (13 tools)

Tool Purpose
getTwitterUser / getTwitterUsers Look up 1-100 users by ID or username
searchTwitterUsers Fuzzy search users by name
getTwitterUserConnections Get followers or following
getTwitterUsersByKeywords Find users who posted about a topic
getTwitterPostsByIds Get 1-100 posts by ID
getTwitterPostsByAuthor Get all posts from a username
getTwitterPostsByKeywords Search posts by keywords
getTwitterPostRetweets Get retweets of a post
getTwitterPostQuotes Get quote tweets of a post
getTwitterPostComments Get replies to a post
getTwitterPostInteractingUsers Get commenters, quoters, or retweeters
countTweets Count tweets matching a phrase

See references/twitter.md for all parameters, fields, and examples.

Instagram (9 tools)

Tool Purpose
getInstagramUser Look up user by ID or username
searchInstagramUsers Fuzzy search users by name
getInstagramUserConnections Get followers or following
getInstagramUsersByKeywords Find users who posted about a topic
getInstagramPostInteractingUsers Get commenters or likers of a post
getInstagramPostsByIds Get posts by strong_id
getInstagramPostsByUser Get posts from a user
getInstagramPostsByKeywords Search posts by keywords in captions/subtitles
getInstagramCommentsByPostId Get comments on a post

See references/instagram.md for all parameters, fields, and examples.

Reddit (9 tools)

Tool Purpose
getRedditUser Look up user by username
searchRedditUsers Fuzzy search users by name
getRedditUsersByKeywords Find users who posted about a topic
getRedditPostsByKeywords Search posts by keywords
getRedditPostWithCommentsById Get a post with all its comments
getRedditCommentsByKeywords Search comments by keywords
searchRedditSubreddits Search subreddits by name
getRedditSubredditWithPostsByName Get subreddit details with posts
getRedditSubredditsByKeywords Search subreddits by keyword in description

See references/reddit.md for all parameters, fields, and examples.

TikTok (9 tools)

Tool Purpose
getTiktokUser Look up user by ID or username
searchTiktokUsers Fuzzy search users by name
getTiktokUsersByKeywords Find users who posted about a topic
getTiktokUsersByHashtags Find users who used specific hashtags
getTiktokPostsByIds Get posts by ID
getTiktokPostsByUser Get posts from a user
getTiktokPostsByKeywords Search posts by keywords
getTiktokPostsByHashtags Search posts by hashtags
getTiktokCommentsByPostId Get comments on a post

See references/tiktok.md for all parameters, fields, and examples.

Tracking

Setting up tracking is a best practice for getting more complete data from Xpoz. Tracked items are crawled regularly in the background, which means:

  • Better coverage — continuous collection captures posts and activity that a single point-in-time query might miss
  • More complete data — tracked items accumulate data over time, giving you a fuller picture than one-off queries

Track keywords, users, subreddits, and hashtags across all 4 platforms.

Supported types per platform:

Platform keyword user subreddit hashtag
Twitter Yes Yes — —
Instagram Yes Yes — —
Reddit Yes Yes Yes —
TikTok Yes Yes — Yes

View current tracking:

MCP:        call getTrackedItems
Python:     client.tracking.get_tracked_items()
TypeScript: await client.tracking.getTrackedItems()
CLI:        xpoz-cli tracking get_tracked_items

Add tracked items:

MCP:        call addTrackedItems with items: [{ phrase: "AI agents", type: "keyword", platform: "twitter" }]
Python:     client.tracking.add_tracked_items([{ "phrase": "AI agents", "type": "keyword", "platform": "twitter" }])
TypeScript: await client.tracking.addTrackedItems([{ phrase: "AI agents", type: "keyword", platform: "twitter" }])
CLI:        xpoz-cli tracking add_tracked_items --items '[{"phrase": "AI agents", "type": "keyword", "platform": "twitter"}]'

Remove tracked items:

MCP:        call removeTrackedItems with items: [{ phrase: "AI agents", type: "keyword", platform: "twitter" }]
Python:     client.tracking.remove_tracked_items([...])
TypeScript: await client.tracking.removeTrackedItems([...])
CLI:        xpoz-cli tracking remove_tracked_items --items '[{"phrase": "AI agents", "type": "keyword", "platform": "twitter"}]'

See xpoz-social-tracking for full tracking workflows and advanced patterns.

Response Modes

All paginated tools support three response modes via responseType:

Mode Behavior Best For
"fast" (default) Returns up to 300 results immediately Quick lookups, exploration
"paging" Async — returns operationId, poll with checkOperationStatus Large datasets, page-by-page
"csv" Async CSV export to S3 — returns download URL Bulk export, offline analysis

See references/pagination-and-export.md for async polling patterns, pagination, and CSV export details.

Field Selection

Pass fields to request only the data you need. This reduces response size and improves performance.

MCP:        fields: ["id", "text", "authorUsername", "likeCount"]
Python:     fields=["id", "text", "author_username", "like_count"]
TypeScript: fields: ["id", "text", "authorUsername", "likeCount"]
CLI:        --fields id text author_username like_count

Each platform has different available fields — see the platform-specific references for complete field lists.

Common Patterns

Search → Analyze → Export:

  1. Search posts by keywords (fast mode) to preview results
  2. Analyze engagement, sentiment, or themes
  3. Export full dataset to CSV for deeper analysis

Find Users → Get Their Posts → Analyze:

  1. Search users by keywords to find relevant accounts
  2. Get posts by author for top accounts
  3. Analyze content patterns, posting frequency, engagement

Data Freshness:

  • Data is cached in Xpoz's database with automatic API fallback when stale — results are kept fresh automatically
  • Use forceLatest: true to bypass cache and force a live fetch (increases latency and cost)

Troubleshooting

Problem Solution
MCP: "Unauthorized" Re-run OAuth flow — see references/authentication.md
SDK: AuthenticationError Verify key at xpoz.ai/settings
Empty results Check query syntax, widen date range, try different keywords
Stale data Use forceLatest: true to bypass cache
Operation timeout Keep polling checkOperationStatus every ~5s until status is no longer running
Token exchange fails Ask user to re-authorize — codes are single-use

Detailed Guides

For complete parameters, response fields, patterns, and examples:

Example Prompts

  • "How do I search for tweets about AI?"
  • "What fields are available for Instagram posts?"
  • "How do I export Reddit data to CSV?"
  • "Set up tracking for my brand across all platforms"
  • "How do I paginate through large result sets?"
  • "What's the difference between fast mode and paging mode?"
  • "How do I authenticate with the Xpoz Python SDK?"
  • "Show me all available TikTok tools"
Files (xpoz-agent-skills)
  • references
    • authentication.md 3.3 KB
      # Authentication
      
      ## Table of Contents
      
      - [Check 1: Already authenticated?](#check-1-already-authenticated)
      - [Recommended: a free access key](#recommended-a-free-access-key)
      - [Path A: MCP](#path-a-mcp)
      - [Path B: SDK (Python or TypeScript)](#path-b-sdk-python-or-typescript)
      - [Path C: CLI](#path-c-cli)
      - [Auth Errors](#auth-errors)
      
      ---
      
      Before fetching data, ensure Xpoz access is configured. Follow these checks in order.
      
      ### Check 1: Already authenticated?
      
      **If you have MCP tools**, try calling any Xpoz tool (e.g., `checkAccessKeyStatus`). If it works → skip to Step 1.
      
      **If you have the SDK**, try:
      ```python
      from xpoz import XpozClient
      client = XpozClient()  # reads XPOZ_API_KEY env var
      ```
      If this succeeds without error → skip to Step 1.
      
      **If you have the CLI**, try:
      ```bash
      xpoz-cli twitter get_user --identifier xpoz --identifier-type username
      ```
      If this returns a result → skip to Step 1.
      
      If none of these work, you need to authenticate. Get a free access key (below).
      
      ---
      
      ### Recommended: a free access key
      
      Real analyses need a real key: [get a free access key](https://xpoz.ai/get-token) (free tier, up to 75K results, no credit card; same API shape as every tier, nothing to rewrite). SDK and CLI users set it as `XPOZ_API_KEY`; MCP connections sign in with the same account via OAuth on first tool call.
      
      ---
      
      ### Path A: MCP
      
      Add the Xpoz MCP server to your agent's configuration. The server URL is:
      
      ```
      https://mcp.xpoz.ai/mcp
      ```
      
      Most MCP-compatible agents (Claude Code, Cursor, Windsurf, etc.) handle OAuth automatically on first tool call — the user just needs to authorize in their browser when prompted.
      
      **Example — Claude Code** (`~/.claude.json`):
      ```json
      {
        "mcpServers": {
          "xpoz": {
            "url": "https://mcp.xpoz.ai/mcp",
            "transport": "streamable-http"
          }
        }
      }
      ```
      
      For other MCP clients, consult your agent's documentation for how to add an MCP server by URL.
      
      ---
      
      ### Path B: SDK (Python or TypeScript)
      
      Ask the user:
      > "I need a Xpoz API key to access social media data. Please go to https://xpoz.ai/get-token and paste the key back to me."
      
      **WAIT for the user to reply with the key.** Then:
      
      **Python:**
      ```bash
      pip install xpoz
      ```
      ```python
      from xpoz import XpozClient
      client = XpozClient("THE_KEY_FROM_USER")
      ```
      
      **TypeScript:**
      ```bash
      npm install @xpoz/xpoz
      ```
      ```typescript
      import { XpozClient } from "@xpoz/xpoz";
      const client = new XpozClient({ apiKey: "THE_KEY_FROM_USER" });
      await client.connect();
      ```
      
      Or set the environment variable and use the default constructor:
      ```bash
      export XPOZ_API_KEY=THE_KEY_FROM_USER
      ```
      
      ---
      
      ### Path C: CLI
      
      The CLI uses the same API key as the SDKs. Ask the user for a key (same as Path B), then:
      
      ```bash
      pip install xpoz-cli
      ```
      
      Set the API key as an environment variable:
      ```bash
      export XPOZ_API_KEY=THE_KEY_FROM_USER
      ```
      
      Or pass it inline with each command:
      ```bash
      xpoz-cli --api-key THE_KEY_FROM_USER twitter search_posts --query "test"
      ```
      
      Verify:
      ```bash
      xpoz-cli twitter get_user --identifier xpoz --identifier-type username
      ```
      
      ---
      
      ### Auth Errors
      | Problem | Solution |
      |---------|----------|
      | MCP: "Unauthorized" | Re-run the OAuth flow above |
      | SDK: `AuthenticationError` | Verify key at [xpoz.ai/settings](https://xpoz.ai/settings) |
      | Token exchange fails | Ask user to re-authorize — codes are single-use |
      
    • cli.md 5.6 KB
      # CLI Reference
      
      ## Table of Contents
      
      - [Installation](#installation)
      - [Command Structure](#command-structure)
      - [Global Options](#global-options)
      - [Parameter Naming](#parameter-naming)
      - [Lists](#lists)
      - [Rendering Modes](#rendering-modes)
        - [Standard (JSON)](#standard-json)
        - [CSV Export](#csv-export)
        - [Paginated Walk](#paginated-walk)
        - [Jump to Page](#jump-to-page)
      - [Examples by Platform](#examples-by-platform)
        - [Twitter](#twitter)
        - [Instagram](#instagram)
        - [Reddit](#reddit)
        - [TikTok](#tiktok)
      
      ---
      
      ## Installation
      
      ```bash
      pip install xpoz-cli
      ```
      
      Verify installation:
      ```bash
      xpoz-cli --help
      ```
      
      ---
      
      ## Command Structure
      
      ```
      xpoz-cli [global-opts] <platform> <method> [--arg value]
      ```
      
      - **platform**: `twitter`, `instagram`, `reddit`, `tiktok`, `tracking`
      - **method**: snake_case SDK method name (e.g., `search_posts`, `get_user`)
      - **args**: method-specific parameters as `--kebab-case` flags
      
      ---
      
      ## Global Options
      
      | Option | Environment Variable | Description |
      |--------|---------------------|-------------|
      | `--api-key KEY` | `XPOZ_API_KEY` | API key for authentication |
      | `--server-url URL` | — | Custom server URL (defaults to production) |
      
      If `--api-key` is not provided, the CLI reads from the `XPOZ_API_KEY` environment variable.
      
      ```bash
      # Using the flag
      xpoz-cli --api-key your-key twitter search_posts --query "AI"
      
      # Using the environment variable
      export XPOZ_API_KEY=your-key
      xpoz-cli twitter search_posts --query "AI"
      ```
      
      ---
      
      ## Parameter Naming
      
      SDK parameter names in **snake_case** are converted to **--kebab-case** flags:
      
      | SDK Parameter | CLI Flag |
      |--------------|----------|
      | `start_date` | `--start-date` |
      | `end_date` | `--end-date` |
      | `identifier_type` | `--identifier-type` |
      | `response_type` | `--response-type` |
      | `page_number` | `--page-number` |
      | `force_latest` | `--force-latest` |
      | `filter_out_retweets` | `--filter-out-retweets` (Twitter only) |
      
      ---
      
      ## Lists
      
      Pass multiple values to list parameters by separating them with spaces:
      
      ```bash
      # Select specific fields
      xpoz-cli twitter search_posts --query "AI" --fields id text author_username like_count
      
      # Multiple identifiers
      xpoz-cli twitter get_users --identifiers elonmusk kaborahane --identifier-type username
      
      # Multiple hashtags
      xpoz-cli tiktok get_posts_by_hashtags --hashtags ai machinelearning deeplearning
      ```
      
      ---
      
      ## Rendering Modes
      
      **Note:** CSV export and paginated walk modes are async operations and may take longer than the default JSON mode.
      
      ### Standard (JSON)
      
      By default, the CLI outputs JSON to stdout.
      
      ```bash
      xpoz-cli twitter search_posts --query "bitcoin" --limit 10
      ```
      
      Output:
      ```json
      {
        "data": [...],
        "pagination": {
          "totalRows": 15000,
          "pageNumber": 1,
          "totalPages": 150
        }
      }
      ```
      
      Pipe to `jq` for filtering:
      ```bash
      xpoz-cli twitter search_posts --query "bitcoin" --limit 10 | jq '.data[].text'
      ```
      
      ### CSV Export
      
      Export results directly to a CSV file on S3 and print the download URL.
      
      ```bash
      xpoz-cli twitter search_posts --query "bitcoin" --response-type csv --export-csv-url
      ```
      
      Output:
      ```
      https://s3.amazonaws.com/xpoz-exports/export_abc123.csv
      ```
      
      ### Paginated Walk
      
      Automatically iterate through all pages and output all results.
      
      ```bash
      # Walk all pages
      xpoz-cli reddit search_posts --query "python" --all-pages
      
      # Walk up to N pages
      xpoz-cli reddit search_posts --query "python" --all-pages --max-pages 5
      ```
      
      ### Jump to Page
      
      Fetch a specific page number from a paginated result set.
      
      ```bash
      xpoz-cli twitter search_posts --query "AI" --response-type paging --page 3
      ```
      
      ---
      
      ## Examples by Platform
      
      ### Twitter
      
      **Search posts with date range and limit:**
      ```bash
      xpoz-cli twitter search_posts --query "bitcoin" --start-date 2025-01-01 --limit 20
      ```
      
      **Get a user profile:**
      ```bash
      xpoz-cli twitter get_user --identifier elonmusk --identifier-type username
      ```
      
      **Get posts by author with field selection:**
      ```bash
      xpoz-cli twitter get_posts_by_author --identifier elonmusk --fields id text like_count retweet_count created_at
      ```
      
      **Count tweets matching a phrase:**
      ```bash
      xpoz-cli twitter count_posts --query "artificial intelligence"
      ```
      
      **Search users who post about a topic:**
      ```bash
      xpoz-cli twitter get_users_by_keywords --query "machine learning researcher"
      ```
      
      ### Instagram
      
      **Get a user profile:**
      ```bash
      xpoz-cli instagram get_user --identifier cristiano
      ```
      
      **Search posts by keyword:**
      ```bash
      xpoz-cli instagram search_posts --query "fitness" --start-date 2025-01-01 --limit 50
      ```
      
      **Get posts from a specific user:**
      ```bash
      xpoz-cli instagram get_posts_by_user --identifier cristiano --limit 20
      ```
      
      **Get comments on a post:**
      ```bash
      xpoz-cli instagram get_comments --post-id "3012345678901234567"
      ```
      
      ### Reddit
      
      **Search posts with subreddit filter and paginate through all results:**
      ```bash
      xpoz-cli reddit search_posts --query "python" --subreddit learnpython --all-pages
      ```
      
      **Get a post with all its comments:**
      ```bash
      xpoz-cli reddit get_post_with_comments --post-id "t3_abc123"
      ```
      
      **Search subreddits by name:**
      ```bash
      xpoz-cli reddit search_subreddits --query "programming"
      ```
      
      **Find users who post about a topic:**
      ```bash
      xpoz-cli reddit get_users_by_keywords --query "data science"
      ```
      
      ### TikTok
      
      **Search posts and export to CSV:**
      ```bash
      xpoz-cli tiktok search_posts --query "ai" --response-type csv --export-csv-url
      ```
      
      **Get a user profile:**
      ```bash
      xpoz-cli tiktok get_user --identifier charlidamelio
      ```
      
      **Search posts by hashtags:**
      ```bash
      xpoz-cli tiktok get_posts_by_hashtags --hashtags ai machinelearning --limit 50
      ```
      
      **Find users who used specific hashtags:**
      ```bash
      xpoz-cli tiktok get_users_by_hashtags --hashtags fitness workout --limit 20
      ```
    • instagram.md 17.5 KB
      # Instagram Tools
      
      ## Table of Contents
      
      - [getInstagramUser](#getinstagramuser)
      - [searchInstagramUsers](#searchinstagramusers)
      - [getInstagramUserConnections](#getinstagramuserconnections)
      - [getInstagramUsersByKeywords](#getinstagramusersbykeywords)
      - [getInstagramPostInteractingUsers](#getinstagrampostinteractingusers)
      - [getInstagramPostsByIds](#getinstagrampostsbyids)
      - [getInstagramPostsByUser](#getinstagrampostsbyuser)
      - [getInstagramPostsByKeywords](#getinstagrampostsbykeywords)
      - [getInstagramCommentsByPostId](#getinstagramcommentsbypostid)
      
      ---
      
      > **strong_id format**: Several Instagram tools require post IDs in `strong_id` format: `{media_id}_{user_id}` (e.g., `"3606450040306139062_4836333238"`). A plain `media_id` will not work. Tools that require this format are marked below.
      
      ---
      
      ## getInstagramUser
      
      Get an Instagram user profile by ID or username.
      
      ### Parameters
      
      | Parameter | Type | Required | Default | Description |
      |-----------|------|----------|---------|-------------|
      | `identifier` | string | Yes | — | User ID or username |
      | `identifierType` | `"id"` \| `"username"` | Yes | — | How to interpret `identifier` |
      | `fields` | string[] | No | `["id", "username", "fullName"]` | Fields to return |
      
      ### Available Fields
      
      `id`, `username`, `fullName`, `biography`, `isPrivate`, `isVerified`, `followerCount`, `followingCount`, `mediaCount`, `profilePicUrl`
      
      ### Examples
      
      **MCP:**
      ```json
      {
        "tool": "getInstagramUser",
        "arguments": {
          "identifier": "natgeo",
          "identifierType": "username",
          "fields": ["id", "username", "fullName", "followerCount", "biography"]
        }
      }
      ```
      
      **Python SDK:**
      ```python
      user = client.instagram.get_user(
          "natgeo",
          identifier_type="username",
          fields=["id", "username", "full_name", "follower_count", "biography"]
      )
      ```
      
      **TypeScript SDK:**
      ```typescript
      const user = await client.instagram.getUser("natgeo", {
        identifierType: "username",
        fields: ["id", "username", "fullName", "followerCount", "biography"],
      });
      ```
      
      **CLI:**
      ```bash
      xpoz-cli instagram get_user natgeo --identifier-type username --fields id username full_name follower_count biography
      ```
      
      ---
      
      ## searchInstagramUsers
      
      Fuzzy search Instagram users by name.
      
      ### Parameters
      
      | Parameter | Type | Required | Default | Description |
      |-----------|------|----------|---------|-------------|
      | `name` | string | Yes | — | Name to search for |
      | `limit` | number | No | 10 | Max results (max 10) |
      | `fields` | string[] | No | `["id", "username", "fullName"]` | Fields to return |
      
      ### Available Fields
      
      Same as [getInstagramUser](#available-fields).
      
      ### Examples
      
      **MCP:**
      ```json
      {
        "tool": "searchInstagramUsers",
        "arguments": {
          "name": "National Geographic",
          "limit": 5,
          "fields": ["id", "username", "fullName", "followerCount", "isVerified"]
        }
      }
      ```
      
      **Python SDK:**
      ```python
      results = client.instagram.search_users(
          "National Geographic",
          limit=5,
          fields=["id", "username", "full_name", "follower_count", "is_verified"]
      )
      ```
      
      **TypeScript SDK:**
      ```typescript
      const results = await client.instagram.searchUsers("National Geographic", {
        limit: 5,
        fields: ["id", "username", "fullName", "followerCount", "isVerified"],
      });
      ```
      
      **CLI:**
      ```bash
      xpoz-cli instagram search_users "National Geographic" --limit 5 --fields id username full_name follower_count is_verified
      ```
      
      ---
      
      ## getInstagramUserConnections
      
      Get followers or following list for a user.
      
      ### Parameters
      
      | Parameter | Type | Required | Default | Description |
      |-----------|------|----------|---------|-------------|
      | `username` | string | Yes | — | Instagram username |
      | `connectionType` | `"followers"` \| `"following"` | Yes | — | Which connection list to retrieve |
      | `fields` | string[] | No | `["id", "username", "fullName"]` | Fields to return |
      | `forceLatest` | boolean | No | false | Bypass cache and fetch from API |
      | `responseType` | `"fast"` \| `"paging"` | No | `"fast"` | Response mode |
      | `limit` | number | No | — | Max results (fast: up to 300) |
      | `pageNumber` | number | No | — | Start page (paging mode) |
      | `pageNumberEnd` | number | No | — | End page (paging mode) |
      | `tableName` | string | No | — | Resume from a previous operation |
      
      ### Response Modes
      
      | Mode | Behavior |
      |------|----------|
      | `"fast"` | Returns up to 300 results immediately |
      | `"paging"` | Async, returns 100 results per page. Returns `operationId` — poll with `checkOperationStatus` |
      
      ### Available Fields
      
      Same as [getInstagramUser](#available-fields).
      
      ### Examples
      
      **MCP:**
      ```json
      {
        "tool": "getInstagramUserConnections",
        "arguments": {
          "username": "natgeo",
          "connectionType": "followers",
          "fields": ["id", "username", "fullName", "followerCount"],
          "responseType": "fast",
          "limit": 100
        }
      }
      ```
      
      **Python SDK:**
      ```python
      followers = client.instagram.get_user_connections(
          "natgeo",
          connection_type="followers",
          fields=["id", "username", "full_name", "follower_count"],
          force_latest=False
      )
      ```
      
      **TypeScript SDK:**
      ```typescript
      const followers = await client.instagram.getUserConnections("natgeo", "followers", {
        fields: ["id", "username", "fullName", "followerCount"],
      });
      ```
      
      **CLI:**
      ```bash
      xpoz-cli instagram get_user_connections natgeo --connection-type followers --fields id username full_name follower_count --response-type fast --limit 100
      ```
      
      ---
      
      ## getInstagramUsersByKeywords
      
      Find users who posted about a topic. Returns users with aggregate engagement metrics for matching posts.
      
      ### Parameters
      
      | Parameter | Type | Required | Default | Description |
      |-----------|------|----------|---------|-------------|
      | `query` | string | Yes | — | Search query (supports boolean syntax) |
      | `fields` | string[] | No | `["id", "username", "fullName"]` | Fields to return |
      | `startDate` | string | No | — | Start date (YYYY-MM-DD) |
      | `endDate` | string | No | — | End date (YYYY-MM-DD) |
      | `forceLatest` | boolean | No | false | Bypass cache and fetch from API |
      | `responseType` | `"fast"` \| `"paging"` \| `"csv"` | No | `"fast"` | Response mode |
      | `limit` | number | No | — | Max results |
      | `pageNumber` | number | No | — | Start page (paging mode) |
      | `pageNumberEnd` | number | No | — | End page (paging mode) |
      | `tableName` | string | No | — | Resume from a previous operation |
      
      ### Available Fields
      
      Standard user fields plus aggregate fields:
      
      **User fields:** `id`, `username`, `fullName`, `biography`, `isPrivate`, `isVerified`, `followerCount`, `followingCount`, `mediaCount`, `profilePicUrl`
      
      **Aggregate fields:** `aggRelevance`, `relevantPostsCount`, `relevantPostsLikesSum`, `relevantPostsCommentsSum`, `relevantPostsResharesSum`, `relevantPostsVideoPlaysSum`
      
      ### Examples
      
      **MCP:**
      ```json
      {
        "tool": "getInstagramUsersByKeywords",
        "arguments": {
          "query": "sustainable fashion",
          "fields": ["id", "username", "fullName", "followerCount", "relevantPostsCount", "relevantPostsLikesSum"],
          "startDate": "2026-01-01",
          "endDate": "2026-06-01"
        }
      }
      ```
      
      **Python SDK:**
      ```python
      users = client.instagram.get_users_by_keywords(
          "sustainable fashion",
          fields=["id", "username", "full_name", "follower_count", "relevant_posts_count", "relevant_posts_likes_sum"],
          start_date="2026-01-01",
          end_date="2026-06-01"
      )
      ```
      
      **TypeScript SDK:**
      ```typescript
      const users = await client.instagram.getUsersByKeywords("sustainable fashion", {
        fields: ["id", "username", "fullName", "followerCount", "relevantPostsCount", "relevantPostsLikesSum"],
        startDate: "2026-01-01",
        endDate: "2026-06-01",
      });
      ```
      
      **CLI:**
      ```bash
      xpoz-cli instagram get_users_by_keywords "sustainable fashion" --fields id username full_name follower_count relevant_posts_count relevant_posts_likes_sum --start-date 2026-01-01 --end-date 2026-06-01
      ```
      
      ---
      
      ## getInstagramPostInteractingUsers
      
      Get users who commented on or liked a specific post.
      
      > **Requires strong_id format** for `postId` (e.g., `"3606450040306139062_4836333238"`).
      
      ### Parameters
      
      | Parameter | Type | Required | Default | Description |
      |-----------|------|----------|---------|-------------|
      | `postId` | string | Yes | — | Post ID in **strong_id** format (`{media_id}_{user_id}`) |
      | `interactionType` | `"commenters"` \| `"likers"` | Yes | — | Which interacting users to retrieve |
      | `fields` | string[] | No | `["id", "username", "fullName"]` | Fields to return |
      | `forceLatest` | boolean | No | false | Bypass cache and fetch from API |
      | `responseType` | `"fast"` \| `"paging"` | No | `"fast"` | Response mode |
      | `limit` | number | No | — | Max results |
      | `pageNumber` | number | No | — | Start page (paging mode) |
      | `pageNumberEnd` | number | No | — | End page (paging mode) |
      | `tableName` | string | No | — | Resume from a previous operation |
      
      ### Available Fields
      
      Same as [getInstagramUser](#available-fields).
      
      ### Examples
      
      **MCP:**
      ```json
      {
        "tool": "getInstagramPostInteractingUsers",
        "arguments": {
          "postId": "3606450040306139062_4836333238",
          "interactionType": "commenters",
          "fields": ["id", "username", "fullName", "followerCount"]
        }
      }
      ```
      
      **Python SDK:**
      ```python
      commenters = client.instagram.get_post_interacting_users(
          "3606450040306139062_4836333238",
          interaction_type="commenters",
          fields=["id", "username", "full_name", "follower_count"],
          force_latest=False
      )
      ```
      
      **TypeScript SDK:**
      ```typescript
      const commenters = await client.instagram.getPostInteractingUsers(
        "3606450040306139062_4836333238",
        "commenters",
        { fields: ["id", "username", "fullName", "followerCount"] }
      );
      ```
      
      **CLI:**
      ```bash
      xpoz-cli instagram get_post_interacting_users "3606450040306139062_4836333238" --interaction-type commenters --fields id username full_name follower_count
      ```
      
      ---
      
      ## getInstagramPostsByIds
      
      Get 1-100 Instagram posts by their IDs.
      
      > **Requires strong_id format** for all IDs in `postIds` (e.g., `"3606450040306139062_4836333238"`). A plain `media_id` will not work.
      
      **Data freshness:** Returns cached data from DB, with automatic API fallback if data is stale (>3 days).
      
      ### Parameters
      
      | Parameter | Type | Required | Default | Description |
      |-----------|------|----------|---------|-------------|
      | `postIds` | string[] | Yes | — | 1-100 post IDs in **strong_id** format |
      | `fields` | string[] | No | `["id", "caption", "username", "createdAtDate"]` | Fields to return |
      | `forceLatest` | boolean | No | false | Bypass cache and fetch from API |
      
      ### Available Fields
      
      `id`, `caption`, `userId`, `username`, `fullName`, `createdAtDate`, `likeCount`, `commentCount`, `reshareCount`, `videoPlayCount`, `mediaType`, `imageUrl`, `videoUrl`, `subtitles`, `videoDuration`
      
      ### Examples
      
      **MCP:**
      ```json
      {
        "tool": "getInstagramPostsByIds",
        "arguments": {
          "postIds": [
            "3606450040306139062_4836333238",
            "3605872119044821507_25025320"
          ],
          "fields": ["id", "caption", "username", "likeCount", "commentCount", "createdAtDate"]
        }
      }
      ```
      
      **Python SDK:**
      ```python
      posts = client.instagram.get_posts_by_ids(
          ["3606450040306139062_4836333238", "3605872119044821507_25025320"],
          fields=["id", "caption", "username", "like_count", "comment_count", "created_at_date"]
      )
      ```
      
      **TypeScript SDK:**
      ```typescript
      const posts = await client.instagram.getPostsByIds(
        ["3606450040306139062_4836333238", "3605872119044821507_25025320"],
        { fields: ["id", "caption", "username", "likeCount", "commentCount", "createdAtDate"] }
      );
      ```
      
      **CLI:**
      ```bash
      xpoz-cli instagram get_posts_by_ids --post-ids "3606450040306139062_4836333238" "3605872119044821507_25025320" --fields id caption username like_count comment_count created_at_date
      ```
      
      ---
      
      ## getInstagramPostsByUser
      
      Get posts from a specific user.
      
      ### Parameters
      
      | Parameter | Type | Required | Default | Description |
      |-----------|------|----------|---------|-------------|
      | `identifier` | string | Yes | — | User ID or username |
      | `identifierType` | `"id"` \| `"username"` | Yes | — | How to interpret `identifier` |
      | `fields` | string[] | No | `["id", "caption", "username", "createdAtDate"]` | Fields to return |
      | `startDate` | string | No | — | Start date (YYYY-MM-DD) |
      | `endDate` | string | No | — | End date (YYYY-MM-DD) |
      | `forceLatest` | boolean | No | false | Bypass cache and fetch from API |
      | `responseType` | `"fast"` \| `"paging"` \| `"csv"` | No | `"fast"` | Response mode |
      | `limit` | number | No | — | Max results |
      | `pageNumber` | number | No | — | Start page (paging mode) |
      | `pageNumberEnd` | number | No | — | End page (paging mode) |
      | `tableName` | string | No | — | Resume from a previous operation |
      
      ### Available Fields
      
      Same as [getInstagramPostsByIds](#available-fields-5).
      
      ### Examples
      
      **MCP:**
      ```json
      {
        "tool": "getInstagramPostsByUser",
        "arguments": {
          "identifier": "natgeo",
          "identifierType": "username",
          "fields": ["id", "caption", "likeCount", "commentCount", "createdAtDate"],
          "startDate": "2026-01-01",
          "endDate": "2026-06-01"
        }
      }
      ```
      
      **Python SDK:**
      ```python
      posts = client.instagram.get_posts_by_user(
          "natgeo",
          identifier_type="username",
          fields=["id", "caption", "like_count", "comment_count", "created_at_date"],
          start_date="2026-01-01",
          end_date="2026-06-01"
      )
      ```
      
      **TypeScript SDK:**
      ```typescript
      const posts = await client.instagram.getPostsByUser("natgeo", {
        identifierType: "username",
        fields: ["id", "caption", "likeCount", "commentCount", "createdAtDate"],
        startDate: "2026-01-01",
        endDate: "2026-06-01",
      });
      ```
      
      **CLI:**
      ```bash
      xpoz-cli instagram get_posts_by_user natgeo --identifier-type username --fields id caption like_count comment_count created_at_date --start-date 2026-01-01 --end-date 2026-06-01
      ```
      
      ---
      
      ## getInstagramPostsByKeywords
      
      Search Instagram posts by keywords in captions and subtitles.
      
      **Data freshness:** Returns cached data from DB, with automatic API fallback if data is stale (>1 week).
      
      ### Parameters
      
      | Parameter | Type | Required | Default | Description |
      |-----------|------|----------|---------|-------------|
      | `query` | string | Yes | — | Search query (supports boolean syntax) |
      | `fields` | string[] | No | `["id", "caption", "username", "createdAtDate"]` | Fields to return |
      | `startDate` | string | No | — | Start date (YYYY-MM-DD) |
      | `endDate` | string | No | — | End date (YYYY-MM-DD) |
      | `forceLatest` | boolean | No | false | Bypass cache and fetch from API |
      | `responseType` | `"fast"` \| `"paging"` \| `"csv"` | No | `"fast"` | Response mode |
      | `limit` | number | No | — | Max results |
      | `pageNumber` | number | No | — | Start page (paging mode) |
      | `pageNumberEnd` | number | No | — | End page (paging mode) |
      | `tableName` | string | No | — | Resume from a previous operation |
      
      ### Available Fields
      
      Same as [getInstagramPostsByIds](#available-fields-5).
      
      ### Examples
      
      **MCP:**
      ```json
      {
        "tool": "getInstagramPostsByKeywords",
        "arguments": {
          "query": "\"artificial intelligence\" AND ethics",
          "fields": ["id", "caption", "username", "likeCount", "createdAtDate"],
          "startDate": "2026-01-01",
          "endDate": "2026-06-01"
        }
      }
      ```
      
      **Python SDK:**
      ```python
      posts = client.instagram.search_posts(
          "\"artificial intelligence\" AND ethics",
          fields=["id", "caption", "username", "like_count", "created_at_date"],
          start_date="2026-01-01",
          end_date="2026-06-01"
      )
      ```
      
      **TypeScript SDK:**
      ```typescript
      const posts = await client.instagram.searchPosts(
        '"artificial intelligence" AND ethics',
        {
          fields: ["id", "caption", "username", "likeCount", "createdAtDate"],
          startDate: "2026-01-01",
          endDate: "2026-06-01",
        }
      );
      ```
      
      **CLI:**
      ```bash
      xpoz-cli instagram search_posts "\"artificial intelligence\" AND ethics" --fields id caption username like_count created_at_date --start-date 2026-01-01 --end-date 2026-06-01
      ```
      
      ---
      
      ## getInstagramCommentsByPostId
      
      Get comments on a specific Instagram post.
      
      > **Requires strong_id format** for `postId` (e.g., `"3606450040306139062_4836333238"`).
      
      ### Parameters
      
      | Parameter | Type | Required | Default | Description |
      |-----------|------|----------|---------|-------------|
      | `postId` | string | Yes | — | Post ID in **strong_id** format (`{media_id}_{user_id}`) |
      | `fields` | string[] | No | `["id", "text", "username", "createdAtDate", "likeCount"]` | Fields to return |
      | `startDate` | string | No | — | Start date (YYYY-MM-DD) |
      | `endDate` | string | No | — | End date (YYYY-MM-DD) |
      | `forceLatest` | boolean | No | false | Bypass cache and fetch from API |
      | `responseType` | `"fast"` \| `"paging"` \| `"csv"` | No | `"fast"` | Response mode |
      | `limit` | number | No | — | Max results |
      | `pageNumber` | number | No | — | Start page (paging mode) |
      | `pageNumberEnd` | number | No | — | End page (paging mode) |
      | `tableName` | string | No | — | Resume from a previous operation |
      
      ### Available Fields
      
      `id`, `text`, `username`, `createdAtDate`, `likeCount`
      
      ### Examples
      
      **MCP:**
      ```json
      {
        "tool": "getInstagramCommentsByPostId",
        "arguments": {
          "postId": "3606450040306139062_4836333238",
          "fields": ["id", "text", "username", "createdAtDate", "likeCount"],
          "limit": 50
        }
      }
      ```
      
      **Python SDK:**
      ```python
      comments = client.instagram.get_comments(
          "3606450040306139062_4836333238",
          fields=["id", "text", "username", "created_at_date", "like_count"],
          start_date="2026-01-01",
          end_date="2026-06-01"
      )
      ```
      
      **TypeScript SDK:**
      ```typescript
      const comments = await client.instagram.getComments(
        "3606450040306139062_4836333238",
        {
          fields: ["id", "text", "username", "createdAtDate", "likeCount"],
          startDate: "2026-01-01",
          endDate: "2026-06-01",
        }
      );
      ```
      
      **CLI:**
      ```bash
      xpoz-cli instagram get_comments "3606450040306139062_4836333238" --fields id text username created_at_date like_count --start-date 2026-01-01 --end-date 2026-06-01
      ```
      
    • pagination-and-export.md 12.9 KB
      # Pagination and Export
      
      ## Table of Contents
      
      - [Response Modes](#response-modes)
        - [Fast Mode (default)](#fast-mode-default)
        - [Paging Mode](#paging-mode)
        - [CSV Export Mode](#csv-export-mode)
      - [The operationId Polling Pattern](#the-operationid-polling-pattern)
      - [Pagination Parameters](#pagination-parameters)
      - [CSV Export](#csv-export)
      - [Cancel Operations](#cancel-operations)
      - [Field Selection](#field-selection)
      
      ---
      
      ## Response Modes
      
      All paginated tools support three response modes via the `responseType` parameter:
      
      
      | Mode   | Value              | Behavior                                                                     | Best For                                    |
      | ------ | ------------------ | ---------------------------------------------------------------------------- | ------------------------------------------- |
      | Fast   | `"fast"` (default) | Returns up to 300 results immediately in a single response                   | Quick lookups, exploration, small datasets  |
      | Paging | `"paging"`         | Async operation — returns an `operationId`, poll with `checkOperationStatus`. SDKs and CLI handle polling automatically | Large datasets, page-by-page iteration      |
      | CSV    | `"csv"`            | Async S3 export — returns a download URL when complete. SDKs and CLI handle polling automatically                       | Bulk export, offline analysis, spreadsheets |
      
      
      ### Fast Mode (default)
      
      Returns up to 300 results synchronously. No polling needed.
      
      **MCP:**
      
      ```json
      {
        "tool": "getTwitterPostsByKeywords",
        "arguments": {
          "query": "artificial intelligence",
          "limit": 100
        }
      }
      ```
      
      **Python SDK:**
      
      ```python
      results = client.twitter.search_posts("artificial intelligence", limit=100)
      for post in results.data:
          print(post["text"])
      ```
      
      **TypeScript SDK:**
      
      ```typescript
      const results = await client.twitter.searchPosts("artificial intelligence", {
        limit: 100,
      });
      for (const post of results.data) {
        console.log(post.text);
      }
      ```
      
      **CLI:**
      
      ```bash
      xpoz-cli twitter search_posts --query "artificial intelligence" --limit 100
      ```
      
      ### Paging Mode
      
      Returns an `operationId` immediately. Poll `checkOperationStatus` to get results page by page.
      
      **MCP:**
      
      ```json
      {
        "tool": "getTwitterPostsByKeywords",
        "arguments": {
          "query": "artificial intelligence",
          "responseType": "paging"
        }
      }
      ```
      
      Response includes `operationId` — use it to poll for results (see [polling pattern](#the-operationid-polling-pattern)).
      
      **Python SDK:**
      
      ```python
      results = client.twitter.search_posts(
          "artificial intelligence",
          response_type="paging"
      )
      # PaginatedResult handles polling automatically
      print(f"Page 1: {len(results.data)} results")
      if results.has_next_page():
          page2 = results.next_page()
      ```
      
      **TypeScript SDK:**
      
      ```typescript
      const results = await client.twitter.searchPosts("artificial intelligence", {
        responseType: "paging",
      });
      console.log(`Page 1: ${results.data.length} results`);
      if (results.hasNextPage()) {
        const page2 = await results.nextPage();
      }
      ```
      
      **CLI:**
      
      ```bash
      # Walk through all pages automatically (stops after 5 pages)
      xpoz-cli twitter search_posts --query "artificial intelligence" --all-pages --max-pages 5
      
      # Jump to a specific page
      xpoz-cli twitter search_posts --query "artificial intelligence" --page 3
      ```
      
      ### CSV Export Mode
      
      Triggers an async export to S3. Poll `checkOperationStatus` to get the `downloadUrl` when ready.
      
      **MCP:**
      
      ```json
      {
        "tool": "getTwitterPostsByKeywords",
        "arguments": {
          "query": "artificial intelligence",
          "responseType": "csv"
        }
      }
      ```
      
      **Python SDK:**
      
      ```python
      results = client.twitter.search_posts(
          "artificial intelligence",
          response_type="csv"
      )
      csv_url = results.export_csv()
      print(f"Download CSV: {csv_url}")
      ```
      
      **TypeScript SDK:**
      
      ```typescript
      const results = await client.twitter.searchPosts("artificial intelligence", {
        responseType: "csv",
      });
      const csvUrl = await results.exportCsv();
      console.log(`Download CSV: ${csvUrl}`);
      ```
      
      **CLI:**
      
      ```bash
      xpoz-cli twitter search_posts --query "artificial intelligence" --response-type csv
      ```
      
      ---
      
      ## The operationId Polling Pattern (MCP only)
      
      When using `paging` or `csv` response modes via MCP, the initial response returns an `operationId`. You must poll `checkOperationStatus` to get the results.
      
      **The Python SDK, TypeScript SDK, and CLI handle polling automatically — you never need to poll manually.**
      
      ### MCP Polling
      
      1. Call the tool with `responseType: "paging"` or `responseType: "csv"`
      2. Extract `operationId` from the response
      3. Call `checkOperationStatus` with the `operationId`
      4. If `status` is `"running"`, wait ~5 seconds and repeat step 3
      5. Keep polling until `status` is `success`, `no_data`, `error`, or `cancelled` — do not stop while running
      
      ```
      Call getTwitterPostsByKeywords:
        query: "bitcoin AND ethereum"
        responseType: "paging"
      
      → Response: { operationId: "op_abc123", status: "running" }
      
      Call checkOperationStatus:
        operationId: "op_abc123"
      
      → If status: "running" → wait ~5 seconds, call again
      → If status: "success" → results are in the response (with tableName, pageNumber, totalRows)
      ```
      
      ### Status Values
      
      
      | Status      | Meaning                                           |
      | ----------- | ------------------------------------------------- |
      | `running`   | Still processing — wait ~5 seconds and poll again |
      | `success`   | Results ready                                     |
      | `no_data`   | No matching results found                         |
      | `error`     | Operation failed                                  |
      | `cancelled` | Cancelled via `cancelOperation`                   |
      
      
      ---
      
      ## Pagination Parameters
      
      After a paging operation completes, use these parameters to navigate through pages:
      
      
      | Parameter       | Type   | Description                                                                         |
      | --------------- | ------ | ----------------------------------------------------------------------------------- |
      | `pageNumber`    | number | 1-indexed page number to fetch                                                      |
      | `pageNumberEnd` | number | Fetch pages from `pageNumber` through `pageNumberEnd` (bulk fetch)                  |
      | `tableName`     | string | Cached table name from the first request's response — required for subsequent pages |
      
      
      ### How Pagination Works
      
      1. The first paging request processes the query and caches results in a temporary table
      2. The response includes `tableName` — pass this on all subsequent page requests
      3. Use `pageNumber` to jump to any page
      4. Use `pageNumberEnd` to fetch a range of pages in one call
      
      ### MCP Pagination Example
      
      **First request (page 1):**
      
      ```json
      {
        "tool": "getTwitterPostsByKeywords",
        "arguments": {
          "query": "machine learning",
          "responseType": "paging"
        }
      }
      ```
      
      Response includes:
      
      ```json
      {
        "pagination": {
          "tableName": "tmp_twitter_posts_abc123",
          "pageNumber": 1,
          "totalRows": 5000,
          "totalPages": 50
        }
      }
      ```
      
      **Subsequent request (page 2):**
      
      ```json
      {
        "tool": "getTwitterPostsByKeywords",
        "arguments": {
          "query": "machine learning",
          "responseType": "paging",
          "tableName": "tmp_twitter_posts_abc123",
          "pageNumber": 2
        }
      }
      ```
      
      **Bulk fetch (pages 2-5):**
      
      ```json
      {
        "tool": "getTwitterPostsByKeywords",
        "arguments": {
          "query": "machine learning",
          "responseType": "paging",
          "tableName": "tmp_twitter_posts_abc123",
          "pageNumber": 2,
          "pageNumberEnd": 5
        }
      }
      ```
      
      ### Python SDK Pagination Example
      
      ```python
      results = client.twitter.search_posts(
          "machine learning",
          response_type="paging"
      )
      
      # Automatic page navigation
      print(f"Page 1: {len(results.data)} results")
      
      if results.has_next_page():
          page2 = results.next_page()
          print(f"Page 2: {len(page2.data)} results")
      
      # Jump to a specific page
      page10 = results.get_page(10)
      print(f"Page 10: {len(page10.data)} results")
      ```
      
      ### TypeScript SDK Pagination Example
      
      ```typescript
      const results = await client.twitter.searchPosts("machine learning", {
        responseType: "paging",
      });
      
      console.log(`Page 1: ${results.data.length} results`);
      
      if (results.hasNextPage()) {
        const page2 = await results.nextPage();
        console.log(`Page 2: ${page2.data.length} results`);
      }
      
      // Jump to a specific page
      const page10 = await results.getPage(10);
      console.log(`Page 10: ${page10.data.length} results`);
      ```
      
      ### CLI Pagination Example
      
      ```bash
      # Walk through all pages automatically
      xpoz-cli twitter search_posts --query "machine learning" --all-pages --max-pages 10
      
      # Jump to a specific page
      xpoz-cli twitter search_posts --query "machine learning" --page 10
      ```
      
      ---
      
      ## CSV Export
      
      There are two ways to trigger a CSV export:
      
      ### Option 1: Set responseType to "csv"
      
      Pass `responseType: "csv"` in the initial request. The operation exports directly to S3.
      
      **MCP:**
      
      ```json
      {
        "tool": "getTwitterPostsByKeywords",
        "arguments": {
          "query": "cryptocurrency",
          "responseType": "csv"
        }
      }
      ```
      
      Poll `checkOperationStatus` — when `status` is `"success"`, the response contains `downloadUrl`.
      
      **Python SDK:**
      
      ```python
      results = client.twitter.search_posts(
          "cryptocurrency",
          response_type="csv"
      )
      csv_url = results.export_csv()
      print(f"Download: {csv_url}")
      ```
      
      **TypeScript SDK:**
      
      ```typescript
      const results = await client.twitter.searchPosts("cryptocurrency", {
        responseType: "csv",
      });
      const csvUrl = await results.exportCsv();
      console.log(`Download: ${csvUrl}`);
      ```
      
      **CLI:**
      
      ```bash
      xpoz-cli twitter search_posts --query "cryptocurrency" --response-type csv
      ```
      
      ### Option 2: Export after paging with dataDumpExportOperationId
      
      After a paging request completes, the response may include a `dataDumpExportOperationId`. Poll `checkOperationStatus` with this ID to get the CSV `downloadUrl`.
      
      **MCP:**
      
      ```json
      {
        "tool": "checkOperationStatus",
        "arguments": {
          "operationId": "the-dataDumpExportOperationId-value"
        }
      }
      ```
      
      When `status` is `"success"`, the response contains `downloadUrl` for the CSV file on S3.
      
      **Python SDK:**
      
      ```python
      results = client.twitter.search_posts(
          "cryptocurrency",
          response_type="paging"
      )
      # After viewing paged results, export the full dataset
      csv_url = results.export_csv()
      ```
      
      **TypeScript SDK:**
      
      ```typescript
      const results = await client.twitter.searchPosts("cryptocurrency", {
        responseType: "paging",
      });
      // After viewing paged results, export the full dataset
      const csvUrl = await results.exportCsv();
      ```
      
      ---
      
      ## Cancel Operations
      
      Cancel a running operation using the `cancelOperation` MCP tool. This is only available via MCP — the SDKs and CLI do not expose a cancel method.
      
      **MCP:**
      
      ```json
      {
        "tool": "cancelOperation",
        "arguments": {
          "operationId": "op_abc123"
        }
      }
      ```
      
      After cancellation, `checkOperationStatus` returns `status: "cancelled"`.
      
      ---
      
      ## Field Selection
      
      Pass a `fields` array to limit which fields are returned in the response. This reduces response size and improves performance.
      
      ### Key Rules
      
      - Each platform has different available fields (see platform-specific references)
      - MCP, TypeScript SDK, and CLI use **camelCase** field names: `likeCount`, `authorUsername`, `createdAt`
      - Python SDK uses **snake_case** field names: `like_count`, `author_username`, `created_at`
      - If `fields` is omitted, all available fields are returned
      
      ### MCP Field Selection
      
      ```json
      {
        "tool": "getTwitterPostsByKeywords",
        "arguments": {
          "query": "AI startups",
          "fields": ["id", "text", "authorUsername", "likeCount", "retweetCount", "createdAt"]
        }
      }
      ```
      
      ### Python SDK Field Selection
      
      ```python
      results = client.twitter.search_posts(
          "AI startups",
          fields=["id", "text", "author_username", "like_count", "retweet_count", "created_at"]
      )
      ```
      
      ### TypeScript SDK Field Selection
      
      ```typescript
      const results = await client.twitter.searchPosts("AI startups", {
        fields: ["id", "text", "authorUsername", "likeCount", "retweetCount", "createdAt"],
      });
      ```
      
      ### CLI Field Selection
      
      ```bash
      xpoz-cli twitter search_posts --query "AI startups" --fields id text author_username like_count retweet_count created_at
      ```
      
      CLI uses **snake_case** field names (same as Python SDK) and accepts them as space-separated values.
      
      ### Example Fields by Platform
      
      **Twitter posts:** `id`, `text`, `authorId`, `authorUsername`, `createdAt`, `createdAtDate`, `likeCount`, `retweetCount`, `replyCount`, `quoteCount`, `impressionCount`, `bookmarkCount`, `lang`, `isRetweet`, `isReply`, `hashtags`, `mentions`, `mediaUrls`, `country`, `region`, `city`
      
      **Instagram posts:** `id`, `strongId`, `authorId`, `authorUsername`, `caption`, `likeCount`, `commentCount`, `viewCount`, `mediaType`, `mediaUrls`, `hashtags`, `createdAt`
      
      **Reddit posts:** `id`, `title`, `text`, `authorUsername`, `subreddit`, `score`, `upvoteRatio`, `commentCount`, `createdAt`, `url`, `permalink`
      
      **TikTok posts:** `id`, `authorId`, `authorUsername`, `description`, `likeCount`, `commentCount`, `shareCount`, `viewCount`, `playCount`, `hashtags`, `createdAt`
      
      For the complete field list per tool, see the platform-specific reference files.
    • reddit.md 17.6 KB
      # Reddit Tools Reference
      
      All 9 Reddit tools with parameters, available fields, and usage examples across MCP, Python SDK, TypeScript SDK, and CLI.
      
      ## Table of Contents
      
      - [getRedditUser](#getreddituser)
      - [searchRedditUsers](#searchredditusers)
      - [getRedditUsersByKeywords](#getreddituserbykeywords)
      - [getRedditPostsByKeywords](#getredditpostsbykeywords)
      - [getRedditPostWithCommentsById](#getredditpostwithcommentsbyid)
      - [getRedditCommentsByKeywords](#getredditcommentsbykeywords)
      - [searchRedditSubreddits](#searchredditsubreddits)
      - [getRedditSubredditWithPostsByName](#getredditsubredditwithpostsbyname)
      - [getRedditSubredditsByKeywords](#getredditsubredditsbykeywords)
      
      ---
      
      ## getRedditUser
      
      Get a Reddit user by username.
      
      ### Parameters
      
      | Parameter | Type | Required | Default | Description |
      |-----------|------|----------|---------|-------------|
      | `username` | string | Yes | — | Reddit username (no `u/` prefix) |
      | `fields` | string[] | No | `["id", "username", "totalKarma"]` | Fields to return |
      
      ### Available Fields
      
      `id`, `username`, `profileUrl`, `profilePicUrl`, `linkKarma`, `commentKarma`, `totalKarma`, `awardeeKarma`, `awarderKarma`, `isGold`, `isMod`, `isEmployee`, `hasVerifiedEmail`, `isSuspended`, `verified`, `profileDescription`, `createdAt`
      
      ### MCP
      
      ```
      Call getRedditUser:
        username: "spez"
        fields: ["id", "username", "totalKarma", "linkKarma", "commentKarma", "profileDescription", "createdAt"]
      ```
      
      ### Python SDK
      
      ```python
      user = client.reddit.get_user(
          "spez",
          fields=["id", "username", "total_karma", "link_karma", "comment_karma", "profile_description", "created_at"]
      )
      ```
      
      ### TypeScript SDK
      
      ```typescript
      const user = await client.reddit.getUser("spez", {
        fields: ["id", "username", "totalKarma", "linkKarma", "commentKarma", "profileDescription", "createdAt"],
      });
      ```
      
      ### CLI
      
      ```bash
      xpoz-cli reddit get_user --username spez --fields id username total_karma link_karma comment_karma profile_description created_at
      ```
      
      ---
      
      ## searchRedditUsers
      
      Fuzzy search Reddit users by name.
      
      ### Parameters
      
      | Parameter | Type | Required | Default | Description |
      |-----------|------|----------|---------|-------------|
      | `name` | string | Yes | — | Name to search for |
      | `limit` | number | No | 50 | Max results (max 50) |
      | `fields` | string[] | No | `["id", "username", "totalKarma"]` | Fields to return |
      
      ### Available Fields
      
      Same as [getRedditUser](#getreddituser).
      
      ### MCP
      
      ```
      Call searchRedditUsers:
        name: "programming"
        limit: 20
        fields: ["id", "username", "totalKarma", "profileDescription"]
      ```
      
      ### Python SDK
      
      ```python
      users = client.reddit.search_users(
          "programming",
          limit=20,
          fields=["id", "username", "total_karma", "profile_description"]
      )
      ```
      
      ### TypeScript SDK
      
      ```typescript
      const users = await client.reddit.searchUsers("programming", {
        limit: 20,
        fields: ["id", "username", "totalKarma", "profileDescription"],
      });
      ```
      
      ### CLI
      
      ```bash
      xpoz-cli reddit search_users --name programming --limit 20 --fields id username total_karma profile_description
      ```
      
      ---
      
      ## getRedditUsersByKeywords
      
      Find Reddit users who posted about a topic.
      
      ### Parameters
      
      | Parameter | Type | Required | Default | Description |
      |-----------|------|----------|---------|-------------|
      | `query` | string | Yes | — | Search query (supports boolean syntax) |
      | `fields` | string[] | No | — | Fields to return (user fields + aggregate fields) |
      | `startDate` | string | No | — | Start date (YYYY-MM-DD) |
      | `endDate` | string | No | — | End date (YYYY-MM-DD) |
      | `subreddit` | string | No | — | Filter to a subreddit (no `r/` prefix) |
      | `forceLatest` | boolean | No | false | Bypass cache for fresh data |
      | `responseType` | string | No | `"fast"` | `"fast"`, `"paging"`, or `"csv"` |
      | `limit` | number | No | — | Max results |
      | `pageNumber` | number | No | — | Start page (paging mode) |
      | `pageNumberEnd` | number | No | — | End page (paging mode) |
      | `tableName` | string | No | — | Resume from a previous operation |
      
      ### Available Fields
      
      User fields from [getRedditUser](#getreddituser), plus aggregate fields:
      
      | Aggregate Field | Description |
      |----------------|-------------|
      | `aggRelevance` | Relevance score for the query |
      | `relevantPostsCount` | Number of posts matching the query |
      | `relevantPostsUpvotesSum` | Total upvotes across matching posts |
      | `relevantPostsCommentsCountSum` | Total comments across matching posts |
      
      ### MCP
      
      ```
      Call getRedditUsersByKeywords:
        query: "rust programming"
        fields: ["id", "username", "totalKarma", "relevantPostsCount", "aggRelevance"]
        startDate: "2026-01-01"
        endDate: "2026-06-10"
        subreddit: "rust"
      ```
      
      ### Python SDK
      
      ```python
      results = client.reddit.get_users_by_keywords(
          "rust programming",
          fields=["id", "username", "total_karma", "relevant_posts_count", "agg_relevance"],
          start_date="2026-01-01",
          end_date="2026-06-10",
          subreddit="rust"
      )
      ```
      
      ### TypeScript SDK
      
      ```typescript
      const results = await client.reddit.getUsersByKeywords("rust programming", {
        fields: ["id", "username", "totalKarma", "relevantPostsCount", "aggRelevance"],
        startDate: "2026-01-01",
        endDate: "2026-06-10",
        subreddit: "rust",
      });
      ```
      
      ### CLI
      
      ```bash
      xpoz-cli reddit get_users_by_keywords --query "rust programming" --fields id username total_karma relevant_posts_count agg_relevance --start-date 2026-01-01 --end-date 2026-06-10 --subreddit rust
      ```
      
      ---
      
      ## getRedditPostsByKeywords
      
      Search Reddit posts by keywords (searches titles and self-text).
      
      ### Parameters
      
      | Parameter | Type | Required | Default | Description |
      |-----------|------|----------|---------|-------------|
      | `query` | string | Yes | — | Search query (supports boolean syntax) |
      | `fields` | string[] | No | `["id", "title", "authorUsername", "subredditName", "createdAtDate"]` | Fields to return |
      | `startDate` | string | No | — | Start date (YYYY-MM-DD) |
      | `endDate` | string | No | — | End date (YYYY-MM-DD) |
      | `sort` | string | No | — | `"relevance"`, `"hot"`, `"top"`, `"new"`, or `"comments"` |
      | `time` | string | No | — | `"hour"`, `"day"`, `"week"`, `"month"`, `"year"`, or `"all"` |
      | `subreddit` | string | No | — | Filter to a subreddit (no `r/` prefix) |
      | `forceLatest` | boolean | No | false | Bypass cache for fresh data |
      | `responseType` | string | No | `"fast"` | `"fast"`, `"paging"`, or `"csv"` |
      | `limit` | number | No | — | Max results |
      | `pageNumber` | number | No | — | Start page (paging mode) |
      | `pageNumberEnd` | number | No | — | End page (paging mode) |
      | `tableName` | string | No | — | Resume from a previous operation |
      
      ### Available Fields
      
      `id`, `title`, `selftext`, `url`, `permalink`, `authorId`, `authorUsername`, `subredditName`, `subredditId`, `score`, `upvotes`, `downvotes`, `upvoteRatio`, `commentsCount`, `crosspostsCount`, `isSelf`, `isVideo`, `over18`, `spoiler`, `locked`, `stickied`, `archived`, `createdAtDate`
      
      ### MCP
      
      ```
      Call getRedditPostsByKeywords:
        query: "\"artificial intelligence\" AND ethics"
        fields: ["id", "title", "selftext", "authorUsername", "subredditName", "score", "commentsCount", "createdAtDate"]
        startDate: "2026-05-01"
        endDate: "2026-06-10"
        sort: "top"
        time: "month"
      ```
      
      ### Python SDK
      
      ```python
      results = client.reddit.search_posts(
          '"artificial intelligence" AND ethics',
          fields=["id", "title", "selftext", "author_username", "subreddit_name", "score", "comments_count", "created_at_date"],
          start_date="2026-05-01",
          end_date="2026-06-10",
          sort="top",
          time="month"
      )
      ```
      
      ### TypeScript SDK
      
      ```typescript
      const results = await client.reddit.searchPosts('"artificial intelligence" AND ethics', {
        fields: ["id", "title", "selftext", "authorUsername", "subredditName", "score", "commentsCount", "createdAtDate"],
        startDate: "2026-05-01",
        endDate: "2026-06-10",
        sort: "top",
        time: "month",
      });
      ```
      
      ### CLI
      
      ```bash
      xpoz-cli reddit search_posts --query "\"artificial intelligence\" AND ethics" --fields id title selftext author_username subreddit_name score comments_count created_at_date --start-date 2026-05-01 --end-date 2026-06-10 --sort top --time month
      ```
      
      ---
      
      ## getRedditPostWithCommentsById
      
      Get a Reddit post with all its comments.
      
      ### Parameters
      
      | Parameter | Type | Required | Default | Description |
      |-----------|------|----------|---------|-------------|
      | `postId` | string | Yes | — | Reddit post ID |
      | `postFields` | string[] | No | — | Fields to return for the post |
      | `commentFields` | string[] | No | — | Fields to return for comments |
      | `forceLatest` | boolean | No | false | Bypass cache for fresh data |
      | `responseType` | string | No | `"fast"` | `"fast"` or `"paging"` |
      | `limit` | number | No | — | Max comments to return |
      | `pageNumber` | number | No | — | Start page (paging mode) |
      | `pageNumberEnd` | number | No | — | End page (paging mode) |
      | `tableName` | string | No | — | Resume from a previous operation |
      
      ### Response Modes
      
      | Mode | Behavior |
      |------|----------|
      | `"fast"` | Returns up to 300 comments immediately |
      | `"paging"` | Async, 100 comments per page — poll with `checkOperationStatus` |
      
      ### Available Post Fields
      
      Same as [getRedditPostsByKeywords](#getredditpostsbykeywords).
      
      ### Available Comment Fields
      
      `id`, `body`, `authorId`, `authorUsername`, `score`, `upvotes`, `parentId`, `depth`, `isSubmitter`, `stickied`, `createdAtDate`
      
      ### MCP
      
      ```
      Call getRedditPostWithCommentsById:
        postId: "1abc2de"
        postFields: ["id", "title", "selftext", "authorUsername", "score", "commentsCount"]
        commentFields: ["id", "body", "authorUsername", "score", "depth", "createdAtDate"]
      ```
      
      ### Python SDK
      
      ```python
      result = client.reddit.get_post_with_comments(
          "1abc2de",
          post_fields=["id", "title", "selftext", "author_username", "score", "comments_count"],
          comment_fields=["id", "body", "author_username", "score", "depth", "created_at_date"]
      )
      ```
      
      ### TypeScript SDK
      
      ```typescript
      const result = await client.reddit.getPostWithComments("1abc2de", {
        postFields: ["id", "title", "selftext", "authorUsername", "score", "commentsCount"],
        commentFields: ["id", "body", "authorUsername", "score", "depth", "createdAtDate"],
      });
      ```
      
      ### CLI
      
      ```bash
      xpoz-cli reddit get_post_with_comments --post-id 1abc2de --post-fields id title selftext author_username score comments_count --comment-fields id body author_username score depth created_at_date
      ```
      
      ---
      
      ## getRedditCommentsByKeywords
      
      Search Reddit comments by keywords (searches comment body text).
      
      **NOTE:** This is a database-only search with no API fallback. Results are limited to comments already indexed by Xpoz.
      
      ### Parameters
      
      | Parameter | Type | Required | Default | Description |
      |-----------|------|----------|---------|-------------|
      | `query` | string | Yes | — | Search query (supports boolean syntax) |
      | `fields` | string[] | No | `["id", "body", "authorUsername", "createdAtDate"]` | Fields to return |
      | `startDate` | string | No | — | Start date (YYYY-MM-DD) |
      | `endDate` | string | No | — | End date (YYYY-MM-DD) |
      | `subreddit` | string | No | — | Filter to a subreddit (no `r/` prefix) |
      | `responseType` | string | No | `"fast"` | `"fast"`, `"paging"`, or `"csv"` |
      | `limit` | number | No | — | Max results |
      | `pageNumber` | number | No | — | Start page (paging mode) |
      | `pageNumberEnd` | number | No | — | End page (paging mode) |
      | `tableName` | string | No | — | Resume from a previous operation |
      
      ### Available Fields
      
      `id`, `body`, `authorId`, `authorUsername`, `score`, `upvotes`, `parentId`, `depth`, `isSubmitter`, `stickied`, `createdAtDate`
      
      ### MCP
      
      ```
      Call getRedditCommentsByKeywords:
        query: "\"type safety\" AND (\"rust\" OR \"typescript\")"
        fields: ["id", "body", "authorUsername", "score", "createdAtDate"]
        startDate: "2026-01-01"
        subreddit: "programming"
      ```
      
      ### Python SDK
      
      ```python
      results = client.reddit.search_comments(
          '"type safety" AND ("rust" OR "typescript")',
          fields=["id", "body", "author_username", "score", "created_at_date"],
          start_date="2026-01-01",
          subreddit="programming"
      )
      ```
      
      ### TypeScript SDK
      
      ```typescript
      const results = await client.reddit.searchComments('"type safety" AND ("rust" OR "typescript")', {
        fields: ["id", "body", "authorUsername", "score", "createdAtDate"],
        startDate: "2026-01-01",
        subreddit: "programming",
      });
      ```
      
      ### CLI
      
      ```bash
      xpoz-cli reddit search_comments --query "\"type safety\" AND (\"rust\" OR \"typescript\")" --fields id body author_username score created_at_date --start-date 2026-01-01 --subreddit programming
      ```
      
      ---
      
      ## searchRedditSubreddits
      
      Search subreddits by name.
      
      ### Parameters
      
      | Parameter | Type | Required | Default | Description |
      |-----------|------|----------|---------|-------------|
      | `query` | string | Yes | — | Subreddit name to search for |
      | `limit` | number | No | 50 | Max results (max 50) |
      | `fields` | string[] | No | — | Fields to return |
      
      ### Available Fields
      
      `id`, `displayName`, `title`, `publicDescription`, `description`, `subscribersCount`, `activeUserCount`, `subredditType`, `over18`, `lang`, `url`, `iconImg`, `createdAt`
      
      ### MCP
      
      ```
      Call searchRedditSubreddits:
        query: "machine learning"
        limit: 10
        fields: ["id", "displayName", "title", "subscribersCount", "activeUserCount", "publicDescription"]
      ```
      
      ### Python SDK
      
      ```python
      subreddits = client.reddit.search_subreddits(
          "machine learning",
          limit=10,
          fields=["id", "display_name", "title", "subscribers_count", "active_user_count", "public_description"]
      )
      ```
      
      ### TypeScript SDK
      
      ```typescript
      const subreddits = await client.reddit.searchSubreddits("machine learning", {
        limit: 10,
        fields: ["id", "displayName", "title", "subscribersCount", "activeUserCount", "publicDescription"],
      });
      ```
      
      ### CLI
      
      ```bash
      xpoz-cli reddit search_subreddits --query "machine learning" --limit 10 --fields id display_name title subscribers_count active_user_count public_description
      ```
      
      ---
      
      ## getRedditSubredditWithPostsByName
      
      Get subreddit details along with its posts.
      
      ### Parameters
      
      | Parameter | Type | Required | Default | Description |
      |-----------|------|----------|---------|-------------|
      | `subredditName` | string | Yes | — | Subreddit name (no `r/` prefix) |
      | `subredditFields` | string[] | No | — | Fields to return for the subreddit |
      | `postFields` | string[] | No | — | Fields to return for posts |
      | `forceLatest` | boolean | No | false | Bypass cache for fresh data |
      | `responseType` | string | No | `"fast"` | `"fast"` or `"paging"` |
      | `limit` | number | No | — | Max posts to return |
      | `pageNumber` | number | No | — | Start page (paging mode) |
      | `pageNumberEnd` | number | No | — | End page (paging mode) |
      | `tableName` | string | No | — | Resume from a previous operation |
      
      ### Available Subreddit Fields
      
      Same as [searchRedditSubreddits](#searchredditsubreddits).
      
      ### Available Post Fields
      
      Same as [getRedditPostsByKeywords](#getredditpostsbykeywords).
      
      ### MCP
      
      ```
      Call getRedditSubredditWithPostsByName:
        subredditName: "LocalLLaMA"
        subredditFields: ["id", "displayName", "subscribersCount", "activeUserCount", "publicDescription"]
        postFields: ["id", "title", "authorUsername", "score", "commentsCount", "createdAtDate"]
      ```
      
      ### Python SDK
      
      ```python
      result = client.reddit.get_subreddit_with_posts(
          "LocalLLaMA",
          subreddit_fields=["id", "display_name", "subscribers_count", "active_user_count", "public_description"],
          post_fields=["id", "title", "author_username", "score", "comments_count", "created_at_date"]
      )
      ```
      
      ### TypeScript SDK
      
      ```typescript
      const result = await client.reddit.getSubredditWithPosts("LocalLLaMA", {
        subredditFields: ["id", "displayName", "subscribersCount", "activeUserCount", "publicDescription"],
        postFields: ["id", "title", "authorUsername", "score", "commentsCount", "createdAtDate"],
      });
      ```
      
      ### CLI
      
      ```bash
      xpoz-cli reddit get_subreddit_with_posts --subreddit-name LocalLLaMA --subreddit-fields id display_name subscribers_count active_user_count public_description --post-fields id title author_username score comments_count created_at_date
      ```
      
      ---
      
      ## getRedditSubredditsByKeywords
      
      Search subreddits by keyword in their descriptions.
      
      ### Parameters
      
      | Parameter | Type | Required | Default | Description |
      |-----------|------|----------|---------|-------------|
      | `query` | string | Yes | — | Search query (supports boolean syntax) |
      | `fields` | string[] | No | — | Fields to return |
      | `startDate` | string | No | — | Start date (YYYY-MM-DD) |
      | `endDate` | string | No | — | End date (YYYY-MM-DD) |
      | `forceLatest` | boolean | No | false | Bypass cache for fresh data |
      | `responseType` | string | No | `"fast"` | `"fast"` or `"paging"` |
      | `limit` | number | No | — | Max results |
      | `pageNumber` | number | No | — | Start page (paging mode) |
      | `pageNumberEnd` | number | No | — | End page (paging mode) |
      | `tableName` | string | No | — | Resume from a previous operation |
      
      ### Available Fields
      
      Same as [searchRedditSubreddits](#searchredditsubreddits).
      
      ### MCP
      
      ```
      Call getRedditSubredditsByKeywords:
        query: "open source AI models"
        fields: ["id", "displayName", "title", "subscribersCount", "publicDescription"]
        startDate: "2026-01-01"
        endDate: "2026-06-10"
      ```
      
      ### Python SDK
      
      ```python
      results = client.reddit.get_subreddits_by_keywords(
          "open source AI models",
          fields=["id", "display_name", "title", "subscribers_count", "public_description"],
          start_date="2026-01-01",
          end_date="2026-06-10"
      )
      ```
      
      ### TypeScript SDK
      
      ```typescript
      const results = await client.reddit.getSubredditsByKeywords("open source AI models", {
        fields: ["id", "displayName", "title", "subscribersCount", "publicDescription"],
        startDate: "2026-01-01",
        endDate: "2026-06-10",
      });
      ```
      
      ### CLI
      
      ```bash
      xpoz-cli reddit get_subreddits_by_keywords --query "open source AI models" --fields id display_name title subscribers_count public_description --start-date 2026-01-01 --end-date 2026-06-10
      ```
      
    • sdk.md 12.3 KB
      # SDK Reference
      
      ## Table of Contents
      
      - [Python SDK](#python-sdk)
        - [Installation](#installation)
        - [Client Setup](#client-setup)
        - [Async Client](#async-client)
        - [Context Manager](#context-manager)
      - [TypeScript SDK](#typescript-sdk)
        - [Installation](#installation-1)
        - [Client Setup](#client-setup-1)
        - [Context Manager](#context-manager-1)
      - [Namespace Pattern](#namespace-pattern)
      - [PaginatedResult Helpers](#paginatedresult-helpers)
      - [Field Naming Convention](#field-naming-convention)
      - [Complete Method Reference](#complete-method-reference)
        - [Twitter (13 methods)](#twitter-13-methods)
        - [Instagram (9 methods)](#instagram-9-methods)
        - [Reddit (9 methods)](#reddit-9-methods)
        - [TikTok (9 methods)](#tiktok-9-methods)
        - [Tracking (3 methods)](#tracking-3-methods)
      
      ---
      
      ## Python SDK
      
      ### Installation
      
      ```bash
      pip install xpoz
      ```
      
      ### Client Setup
      
      ```python
      from xpoz import XpozClient
      
      # Option 1: Reads XPOZ_API_KEY environment variable automatically
      client = XpozClient()
      
      # Option 2: Pass API key directly
      client = XpozClient(api_key="your-api-key")
      
      # Always close when done
      client.close()
      ```
      
      ### Async Client
      
      ```python
      from xpoz import AsyncXpozClient
      
      async def main():
          client = AsyncXpozClient()
          results = await client.twitter.search_posts("artificial intelligence")
          print(f"Found {results.pagination.total_rows:,} tweets")
          await client.close()
      ```
      
      ### Context Manager
      
      ```python
      from xpoz import XpozClient
      
      # Sync context manager — auto-closes on exit
      with XpozClient() as client:
          results = client.twitter.search_posts("artificial intelligence")
          print(f"Found {results.pagination.total_rows:,} tweets")
      ```
      
      ```python
      from xpoz import AsyncXpozClient
      
      # Async context manager
      async with AsyncXpozClient() as client:
          results = await client.twitter.search_posts("artificial intelligence")
          print(f"Found {results.pagination.total_rows:,} tweets")
      ```
      
      ---
      
      ## TypeScript SDK
      
      ### Installation
      
      ```bash
      npm install @xpoz/xpoz
      ```
      
      ### Client Setup
      
      ```typescript
      import { XpozClient } from "@xpoz/xpoz";
      
      // Option 1: Reads XPOZ_API_KEY environment variable automatically
      const client = new XpozClient();
      await client.connect(); // Required — must be called before any tool use
      
      // Option 2: Pass API key directly
      const client = new XpozClient({ apiKey: "your-api-key" });
      await client.connect();
      
      // Always close when done
      await client.close();
      ```
      
      ### Context Manager
      
      ```typescript
      import { XpozClient } from "@xpoz/xpoz";
      
      // await using — auto-closes on scope exit
      {
        await using client = new XpozClient();
        await client.connect();
        const results = await client.twitter.searchPosts("artificial intelligence");
        console.log(`Found ${results.pagination.totalRows.toLocaleString()} tweets`);
      }
      // client.close() called automatically
      ```
      
      ---
      
      ## Namespace Pattern
      
      Both SDKs organize methods by platform namespace:
      
      | Namespace | Accessor | Platforms |
      |-----------|----------|-----------|
      | Twitter | `client.twitter` | Twitter/X |
      | Instagram | `client.instagram` | Instagram |
      | Reddit | `client.reddit` | Reddit |
      | TikTok | `client.tiktok` | TikTok |
      | Tracking | `client.tracking` | Cross-platform tracking |
      | Account | `client.account` | Account details & billing |
      
      **Python:**
      ```python
      client.twitter.search_posts("query")
      client.instagram.get_user("cristiano")
      client.reddit.search_posts("query")
      client.tiktok.search_posts("query")
      client.tracking.get_tracked_items()
      client.account.get_account_details()
      ```
      
      **TypeScript:**
      ```typescript
      await client.twitter.searchPosts("query");
      await client.instagram.getUser("cristiano");
      await client.reddit.searchPosts("query");
      await client.tiktok.searchPosts("query");
      await client.tracking.getTrackedItems();
      await client.account.getAccountDetails();
      ```
      
      ---
      
      ## PaginatedResult Helpers
      
      Tools that return paginated data wrap results in a `PaginatedResult` object with navigation helpers.
      
      ### Python PaginatedResult
      
      ```python
      results = client.twitter.search_posts("AI", response_type="paging")
      
      # Check if more pages exist
      results.has_next_page()  # → bool
      
      # Fetch the next page
      next_results = results.next_page()  # → PaginatedResult
      
      # Jump to a specific page (1-indexed)
      page5 = results.get_page(5)  # → PaginatedResult
      
      # Export the full result set to CSV and get the download URL
      csv_url = results.export_csv()  # → str (S3 download URL)
      ```
      
      ### TypeScript PaginatedResult
      
      ```typescript
      const results = await client.twitter.searchPosts("AI", {
        responseType: "paging",
      });
      
      // Check if more pages exist
      results.hasNextPage(); // → boolean
      
      // Fetch the next page
      const nextResults = await results.nextPage(); // → PaginatedResult
      
      // Jump to a specific page (1-indexed)
      const page5 = await results.getPage(5); // → PaginatedResult
      
      // Export the full result set to CSV and get the download URL
      const csvUrl = await results.exportCsv(); // → Promise<string> (S3 download URL)
      ```
      
      ### Full Iteration Example
      
      **Python:**
      ```python
      results = client.twitter.search_posts("AI agents", response_type="paging")
      all_posts = list(results.data)
      
      while results.has_next_page():
          results = results.next_page()
          all_posts.extend(results.data)
      
      print(f"Collected {len(all_posts)} posts across all pages")
      ```
      
      **TypeScript:**
      ```typescript
      let results = await client.twitter.searchPosts("AI agents", {
        responseType: "paging",
      });
      const allPosts = [...results.data];
      
      while (results.hasNextPage()) {
        results = await results.nextPage();
        allPosts.push(...results.data);
      }
      
      console.log(`Collected ${allPosts.length} posts across all pages`);
      ```
      
      ---
      
      ## Field Naming Convention
      
      Python SDK uses **snake_case** for all field names. TypeScript SDK and MCP use **camelCase**.
      
      | MCP / TypeScript | Python |
      |-----------------|--------|
      | `likeCount` | `like_count` |
      | `authorUsername` | `author_username` |
      | `createdAt` | `created_at` |
      | `followersCount` | `followers_count` |
      | `retweetCount` | `retweet_count` |
      | `commentCount` | `comment_count` |
      | `profileImageUrl` | `profile_image_url` |
      | `mediaUrls` | `media_urls` |
      | `isRetweet` | `is_retweet` |
      | `upvoteRatio` | `upvote_ratio` |
      
      This applies to both the `fields` parameter (input) and the returned data (output).
      
      **Python:**
      ```python
      results = client.twitter.search_posts(
          "AI",
          fields=["id", "text", "like_count", "author_username"]
      )
      for post in results.data:
          print(post["like_count"])
      ```
      
      **TypeScript:**
      ```typescript
      const results = await client.twitter.searchPosts("AI", {
        fields: ["id", "text", "likeCount", "authorUsername"],
      });
      for (const post of results.data) {
        console.log(post.likeCount);
      }
      ```
      
      ---
      
      ## Complete Method Reference
      
      ### Twitter (13 methods)
      
      | Python (snake_case) | TypeScript (camelCase) | Description |
      |---------------------|----------------------|-------------|
      | `client.twitter.get_user(identifier)` | `client.twitter.getUser(identifier)` | Get a single user by ID or username |
      | `client.twitter.get_users(identifiers)` | `client.twitter.getUsers(identifiers)` | Get 1-100 users by IDs or usernames |
      | `client.twitter.search_users(query)` | `client.twitter.searchUsers(query)` | Fuzzy search users by name |
      | `client.twitter.get_user_connections(identifier)` | `client.twitter.getUserConnections(identifier)` | Get followers or following list |
      | `client.twitter.get_users_by_keywords(query)` | `client.twitter.getUsersByKeywords(query)` | Find users who posted about a topic |
      | `client.twitter.get_posts_by_ids(ids)` | `client.twitter.getPostsByIds(ids)` | Get 1-100 posts by ID |
      | `client.twitter.get_posts_by_author(identifier)` | `client.twitter.getPostsByAuthor(identifier)` | Get all posts from a username |
      | `client.twitter.search_posts(query)` | `client.twitter.searchPosts(query)` | Search posts by keywords |
      | `client.twitter.get_retweets(post_id)` | `client.twitter.getRetweets(postId)` | Get retweets of a post |
      | `client.twitter.get_quotes(post_id)` | `client.twitter.getQuotes(postId)` | Get quote tweets of a post |
      | `client.twitter.get_comments(post_id)` | `client.twitter.getComments(postId)` | Get replies to a post |
      | `client.twitter.get_post_interacting_users(post_id)` | `client.twitter.getPostInteractingUsers(postId)` | Get commenters, quoters, or retweeters |
      | `client.twitter.count_posts(query)` | `client.twitter.countPosts(query)` | Count tweets matching a phrase |
      
      ### Instagram (9 methods)
      
      | Python (snake_case) | TypeScript (camelCase) | Description |
      |---------------------|----------------------|-------------|
      | `client.instagram.get_user(identifier)` | `client.instagram.getUser(identifier)` | Get a user by ID or username |
      | `client.instagram.search_users(query)` | `client.instagram.searchUsers(query)` | Fuzzy search users by name |
      | `client.instagram.get_user_connections(identifier)` | `client.instagram.getUserConnections(identifier)` | Get followers or following list |
      | `client.instagram.get_users_by_keywords(query)` | `client.instagram.getUsersByKeywords(query)` | Find users who posted about a topic |
      | `client.instagram.get_post_interacting_users(post_id)` | `client.instagram.getPostInteractingUsers(postId)` | Get commenters or likers of a post |
      | `client.instagram.get_posts_by_ids(ids)` | `client.instagram.getPostsByIds(ids)` | Get posts by strong_id |
      | `client.instagram.get_posts_by_user(identifier)` | `client.instagram.getPostsByUser(identifier)` | Get posts from a user |
      | `client.instagram.search_posts(query)` | `client.instagram.searchPosts(query)` | Search posts by keywords in captions |
      | `client.instagram.get_comments(post_id)` | `client.instagram.getComments(postId)` | Get comments on a post |
      
      ### Reddit (9 methods)
      
      | Python (snake_case) | TypeScript (camelCase) | Description |
      |---------------------|----------------------|-------------|
      | `client.reddit.get_user(identifier)` | `client.reddit.getUser(identifier)` | Get a user by username |
      | `client.reddit.search_users(query)` | `client.reddit.searchUsers(query)` | Fuzzy search users by name |
      | `client.reddit.get_users_by_keywords(query)` | `client.reddit.getUsersByKeywords(query)` | Find users who posted about a topic |
      | `client.reddit.search_posts(query)` | `client.reddit.searchPosts(query)` | Search posts by keywords |
      | `client.reddit.get_post_with_comments(post_id)` | `client.reddit.getPostWithComments(postId)` | Get a post with all its comments |
      | `client.reddit.search_comments(query)` | `client.reddit.searchComments(query)` | Search comments by keywords |
      | `client.reddit.search_subreddits(query)` | `client.reddit.searchSubreddits(query)` | Search subreddits by name |
      | `client.reddit.get_subreddit_with_posts(name)` | `client.reddit.getSubredditWithPosts(name)` | Get subreddit details with posts |
      | `client.reddit.get_subreddits_by_keywords(query)` | `client.reddit.getSubredditsByKeywords(query)` | Search subreddits by keyword in description |
      
      ### TikTok (9 methods)
      
      | Python (snake_case) | TypeScript (camelCase) | Description |
      |---------------------|----------------------|-------------|
      | `client.tiktok.get_user(identifier)` | `client.tiktok.getUser(identifier)` | Get a user by ID or username |
      | `client.tiktok.search_users(query)` | `client.tiktok.searchUsers(query)` | Fuzzy search users by name |
      | `client.tiktok.get_users_by_keywords(query)` | `client.tiktok.getUsersByKeywords(query)` | Find users who posted about a topic |
      | `client.tiktok.get_users_by_hashtags(hashtags)` | `client.tiktok.getUsersByHashtags(hashtags)` | Find users who used specific hashtags |
      | `client.tiktok.get_posts_by_ids(ids)` | `client.tiktok.getPostsByIds(ids)` | Get posts by ID |
      | `client.tiktok.get_posts_by_user(identifier)` | `client.tiktok.getPostsByUser(identifier)` | Get posts from a user |
      | `client.tiktok.search_posts(query)` | `client.tiktok.searchPosts(query)` | Search posts by keywords |
      | `client.tiktok.get_posts_by_hashtags(hashtags)` | `client.tiktok.getPostsByHashtags(hashtags)` | Search posts by hashtags |
      | `client.tiktok.get_comments(post_id)` | `client.tiktok.getComments(postId)` | Get comments on a post |
      
      ### Tracking (3 methods)
      
      | Python (snake_case) | TypeScript (camelCase) | Description |
      |---------------------|----------------------|-------------|
      | `client.tracking.get_tracked_items()` | `client.tracking.getTrackedItems()` | List all tracked items |
      | `client.tracking.add_tracked_items(items)` | `client.tracking.addTrackedItems(items)` | Add items to tracking |
      | `client.tracking.remove_tracked_items(items)` | `client.tracking.removeTrackedItems(items)` | Remove items from tracking |
    • tiktok.md 21.1 KB
      # TikTok Tools
      
      ## Table of Contents
      
      - [getTiktokUser](#gettiktokuser) -- Get user by ID or username
      - [searchTiktokUsers](#searchtiktokusers) -- Fuzzy search users by name
      - [getTiktokUsersByKeywords](#gettiktokuserbykeywords) -- Find users who posted about a topic
      - [getTiktokUsersByHashtags](#gettiktokuserbyhashtags) -- Find users by hashtags (UNIQUE to TikTok)
      - [getTiktokPostsByIds](#gettiktokpostsbyids) -- Get posts by ID
      - [getTiktokPostsByUser](#gettiktokpostsbyuser) -- Get posts from a user
      - [getTiktokPostsByKeywords](#gettiktokpostsbykeywords) -- Search posts by keywords
      - [getTiktokPostsByHashtags](#gettiktokpostsbyhashtags) -- Search posts by hashtags (UNIQUE to TikTok)
      - [getTiktokCommentsByPostId](#gettiktokcommentsbypostid) -- Get comments on a post
      
      ---
      
      ## User Fields
      
      Available on all user tools via the `fields` parameter.
      
      | Field | Description |
      |-------|-------------|
      | `id` | Numeric user ID |
      | `username` | Unique handle |
      | `nickname` | Display name |
      | `signature` | Bio / description |
      | `isPrivate` | Whether the account is private |
      | `isVerified` | Whether the account is verified |
      | `followerCount` | Number of followers |
      | `followingCount` | Number of accounts followed |
      | `likeCount` | Total likes received across posts |
      | `postCount` | Number of posts |
      | `avatar` | Profile picture URL |
      
      Default user fields: `["id", "username", "nickname"]`
      
      ## Post Fields
      
      Available on all post tools via the `fields` parameter.
      
      | Field | Category | Description |
      |-------|----------|-------------|
      | `id` | Core | Post ID |
      | `description` | Core | Post caption / text |
      | `userId` | Core | Author user ID |
      | `username` | Core | Author username |
      | `nickname` | Core | Author display name |
      | `createdAtDate` | Core | Post date (YYYY-MM-DD) |
      | `likeCount` | Engagement | Likes |
      | `commentCount` | Engagement | Comments |
      | `playCount` | Engagement | Video views |
      | `forwardCount` | Engagement | Shares / forwards |
      | `collectCount` | Engagement | Bookmarks / saves |
      | `downloadCount` | Engagement | Downloads |
      | `videoThumbnail` | Media | Thumbnail image URL |
      | `videoUrl` | Media | Video URL |
      | `duration` | Media | Video length |
      | `postType` | Media | Type of post |
      | `hashtags` | Content | Hashtags on the post |
      
      Default post fields: `["id", "description", "username", "createdAtDate"]`
      
      ## Comment Fields
      
      Available on `getTiktokCommentsByPostId` via the `fields` parameter.
      
      | Field | Description |
      |-------|-------------|
      | `id` | Comment ID |
      | `text` | Comment text |
      | `postId` | Parent post ID |
      | `userId` | Commenter user ID |
      | `username` | Commenter username |
      | `likeCount` | Likes on the comment |
      | `createdAt` | Full timestamp |
      | `createdAtTimestamp` | Unix timestamp |
      | `createdAtDate` | Date (YYYY-MM-DD) |
      
      Default comment fields: `["id", "text", "username", "createdAtDate"]`
      
      ## Aggregate Fields (Users by Keywords / Hashtags)
      
      These fields are available on `getTiktokUsersByKeywords` and `getTiktokUsersByHashtags` and must be explicitly requested in the `fields` array.
      
      | Field | Description |
      |-------|-------------|
      | `aggRelevance` | Relevance score based on matching posts |
      | `relevantPostsCount` | Number of matching posts by this user |
      | `relevantPostsLikesSum` | Total likes on matching posts |
      | `relevantPostsCommentsSum` | Total comments on matching posts |
      | `relevantPostsPlaysSum` | Total plays on matching posts |
      | `relevantPostsForwardsSum` | Total forwards on matching posts |
      
      ---
      
      ## getTiktokUser
      
      Get a TikTok user profile by ID or username.
      
      ### Parameters
      
      | Parameter | Type | Required | Default | Description |
      |-----------|------|----------|---------|-------------|
      | `identifier` | string | Yes | -- | User ID or username |
      | `identifierType` | `"id"` \| `"username"` | Yes | -- | Whether `identifier` is a numeric ID or username |
      | `fields` | string[] | No | `["id", "username", "nickname"]` | Fields to return (see User Fields above) |
      
      ### When to use
      
      - You have an exact username or user ID
      - You want a single user profile
      
      For fuzzy/name-based search, use `searchTiktokUsers` instead.
      
      ### MCP
      
      ```json
      {
        "tool": "getTiktokUser",
        "arguments": {
          "identifier": "charlidamelio",
          "identifierType": "username",
          "fields": ["id", "username", "nickname", "followerCount", "isVerified"]
        }
      }
      ```
      
      ### Python SDK
      
      ```python
      user = client.tiktok.get_user(
          "charlidamelio",
          identifier_type="username",
          fields=["id", "username", "nickname", "follower_count", "is_verified"]
      )
      ```
      
      ### TypeScript SDK
      
      ```typescript
      const user = await client.tiktok.getUser("charlidamelio", {
        identifierType: "username",
        fields: ["id", "username", "nickname", "followerCount", "isVerified"],
      });
      ```
      
      ### CLI
      
      ```bash
      xpoz-cli tiktok get_user charlidamelio \
        --identifier-type username \
        --fields id username nickname follower_count is_verified
      ```
      
      ---
      
      ## searchTiktokUsers
      
      Fuzzy search TikTok users by name or username via external API.
      
      ### Parameters
      
      | Parameter | Type | Required | Default | Description |
      |-----------|------|----------|---------|-------------|
      | `name` | string | Yes | -- | Name or username to search for |
      | `limit` | number | No | 10 | Max results (max 10) |
      | `fields` | string[] | No | `["id", "username", "nickname"]` | Fields to return |
      
      ### When to use
      
      - You have a display name, partial name, or approximate username
      - You want to discover multiple candidate users
      
      For exact username lookup, use `getTiktokUser` instead.
      
      ### MCP
      
      ```json
      {
        "tool": "searchTiktokUsers",
        "arguments": {
          "name": "Charli D'Amelio",
          "limit": 5,
          "fields": ["id", "username", "nickname", "followerCount"]
        }
      }
      ```
      
      ### Python SDK
      
      ```python
      users = client.tiktok.search_users(
          "Charli D'Amelio",
          limit=5,
          fields=["id", "username", "nickname", "follower_count"]
      )
      ```
      
      ### TypeScript SDK
      
      ```typescript
      const users = await client.tiktok.searchUsers("Charli D'Amelio", {
        limit: 5,
        fields: ["id", "username", "nickname", "followerCount"],
      });
      ```
      
      ### CLI
      
      ```bash
      xpoz-cli tiktok search_users "Charli D'Amelio" \
        --limit 5 \
        --fields id username nickname follower_count
      ```
      
      ---
      
      ## getTiktokUsersByKeywords
      
      Find TikTok users who authored posts matching keywords. Returns deduplicated user profiles.
      
      ### Parameters
      
      | Parameter | Type | Required | Default | Description |
      |-----------|------|----------|---------|-------------|
      | `query` | string | Yes | -- | Keyword query (supports boolean syntax) |
      | `fields` | string[] | No | `["id", "username", "nickname"]` | Fields to return (user fields + aggregate fields) |
      | `startDate` | string | No | -- | Start date (YYYY-MM-DD) |
      | `endDate` | string | No | -- | End date (YYYY-MM-DD) |
      | `forceLatest` | boolean | No | false | Bypass cache for fresh data |
      | `responseType` | `"fast"` \| `"paging"` \| `"csv"` | No | `"fast"` | Response mode |
      | `limit` | number | No | -- | Max results (fast mode) |
      | `pageNumber` | number | No | -- | Page to fetch (paging mode, 1-indexed) |
      | `pageNumberEnd` | number | No | -- | Last page to fetch (bulk paging) |
      | `tableName` | string | No | -- | Cached table from previous page request |
      
      ### MCP
      
      ```json
      {
        "tool": "getTiktokUsersByKeywords",
        "arguments": {
          "query": "skincare routine",
          "fields": ["id", "username", "nickname", "followerCount", "relevantPostsCount", "relevantPostsPlaysSum"],
          "startDate": "2025-01-01"
        }
      }
      ```
      
      ### Python SDK
      
      ```python
      users = client.tiktok.get_users_by_keywords(
          "skincare routine",
          fields=["id", "username", "nickname", "follower_count", "relevant_posts_count", "relevant_posts_plays_sum"],
          start_date="2025-01-01"
      )
      ```
      
      ### TypeScript SDK
      
      ```typescript
      const users = await client.tiktok.getUsersByKeywords("skincare routine", {
        fields: ["id", "username", "nickname", "followerCount", "relevantPostsCount", "relevantPostsPlaysSum"],
        startDate: "2025-01-01",
      });
      ```
      
      ### CLI
      
      ```bash
      xpoz-cli tiktok get_users_by_keywords "skincare routine" \
        --fields id username nickname follower_count relevant_posts_count relevant_posts_plays_sum \
        --start-date 2025-01-01
      ```
      
      ---
      
      ## getTiktokUsersByHashtags
      
      > **UNIQUE TO TIKTOK** -- This tool has no equivalent on other platforms.
      
      Find TikTok users who authored posts tagged with specific hashtags. Returns deduplicated user profiles.
      
      ### Parameters
      
      | Parameter | Type | Required | Default | Description |
      |-----------|------|----------|---------|-------------|
      | `hashtags` | string[] | Yes | -- | 1-5 bare alphanumeric tags (no `#` prefix) |
      | `fields` | string[] | No | `["id", "username", "nickname"]` | Fields to return (user fields + aggregate fields) |
      | `startDate` | string | No | -- | Start date (YYYY-MM-DD) |
      | `endDate` | string | No | -- | End date (YYYY-MM-DD) |
      | `forceLatest` | boolean | No | false | Bypass cache for fresh data |
      | `responseType` | `"fast"` \| `"paging"` \| `"csv"` | No | `"fast"` | Response mode |
      | `limit` | number | No | -- | Max results (fast mode) |
      | `pageNumber` | number | No | -- | Page to fetch (paging mode, 1-indexed) |
      | `pageNumberEnd` | number | No | -- | Last page to fetch (bulk paging) |
      | `tableName` | string | No | -- | Cached table from previous page request |
      
      ### Hashtag rules
      
      - Pass bare strings: `["fyp", "skincare"]`, not `["#fyp", "#skincare"]`
      - Alphanumeric and underscores only
      - 1-5 hashtags per request
      - OR semantics: matches users who posted with ANY of the listed hashtags
      
      ### When to use
      
      - You want to find creators who used specific TikTok hashtags
      - You are doing hashtag-based influencer discovery
      - You want to see who is participating in a hashtag trend
      
      For keyword/phrase search in post descriptions, use `getTiktokUsersByKeywords` instead.
      
      ### MCP
      
      ```json
      {
        "tool": "getTiktokUsersByHashtags",
        "arguments": {
          "hashtags": ["fyp", "skincare", "beautytok"],
          "fields": ["id", "username", "nickname", "followerCount", "relevantPostsCount"],
          "startDate": "2025-01-01"
        }
      }
      ```
      
      ### Python SDK
      
      ```python
      users = client.tiktok.get_users_by_hashtags(
          ["fyp", "skincare", "beautytok"],
          fields=["id", "username", "nickname", "follower_count", "relevant_posts_count"],
          start_date="2025-01-01"
      )
      ```
      
      ### TypeScript SDK
      
      ```typescript
      const users = await client.tiktok.getUsersByHashtags(["fyp", "skincare", "beautytok"], {
        fields: ["id", "username", "nickname", "followerCount", "relevantPostsCount"],
        startDate: "2025-01-01",
      });
      ```
      
      ### CLI
      
      ```bash
      xpoz-cli tiktok get_users_by_hashtags \
        --hashtags fyp skincare beautytok \
        --fields id username nickname follower_count relevant_posts_count \
        --start-date 2025-01-01
      ```
      
      ---
      
      ## getTiktokPostsByIds
      
      Get TikTok posts by their IDs (1-100 per request). Searches the database first, then falls back to the external API for missing or stale data (>3 days).
      
      ### Parameters
      
      | Parameter | Type | Required | Default | Description |
      |-----------|------|----------|---------|-------------|
      | `postIds` | string[] | Yes | -- | 1-100 post IDs |
      | `fields` | string[] | No | `["id", "description", "username", "createdAtDate"]` | Fields to return (see Post Fields above) |
      | `forceLatest` | boolean | No | false | Bypass cache for fresh data |
      
      ### MCP
      
      ```json
      {
        "tool": "getTiktokPostsByIds",
        "arguments": {
          "postIds": ["7234567890123456789", "7234567890123456790"],
          "fields": ["id", "description", "username", "likeCount", "playCount"]
        }
      }
      ```
      
      ### Python SDK
      
      ```python
      posts = client.tiktok.get_posts_by_ids(
          ["7234567890123456789", "7234567890123456790"],
          fields=["id", "description", "username", "like_count", "play_count"]
      )
      ```
      
      ### TypeScript SDK
      
      ```typescript
      const posts = await client.tiktok.getPostsByIds(
        ["7234567890123456789", "7234567890123456790"],
        { fields: ["id", "description", "username", "likeCount", "playCount"] }
      );
      ```
      
      ### CLI
      
      ```bash
      xpoz-cli tiktok get_posts_by_ids \
        --post-ids 7234567890123456789 7234567890123456790 \
        --fields id description username like_count play_count
      ```
      
      ---
      
      ## getTiktokPostsByUser
      
      Get posts from a TikTok user by ID or username. Searches the database first, then falls back to the external API for stale or missing data.
      
      ### Parameters
      
      | Parameter | Type | Required | Default | Description |
      |-----------|------|----------|---------|-------------|
      | `identifier` | string | Yes | -- | User ID or username |
      | `identifierType` | `"id"` \| `"username"` | Yes | -- | Whether `identifier` is a numeric ID or username |
      | `fields` | string[] | No | `["id", "description", "username", "createdAtDate"]` | Fields to return |
      | `startDate` | string | No | -- | Start date (YYYY-MM-DD) |
      | `endDate` | string | No | -- | End date (YYYY-MM-DD) |
      | `forceLatest` | boolean | No | false | Bypass cache for fresh data |
      | `responseType` | `"fast"` \| `"paging"` \| `"csv"` | No | `"fast"` | Response mode |
      | `limit` | number | No | -- | Max results (fast mode) |
      | `pageNumber` | number | No | -- | Page to fetch (paging mode, 1-indexed) |
      | `pageNumberEnd` | number | No | -- | Last page to fetch (bulk paging) |
      | `tableName` | string | No | -- | Cached table from previous page request |
      
      ### MCP
      
      ```json
      {
        "tool": "getTiktokPostsByUser",
        "arguments": {
          "identifier": "charlidamelio",
          "identifierType": "username",
          "fields": ["id", "description", "likeCount", "playCount", "createdAtDate", "hashtags"],
          "startDate": "2025-01-01"
        }
      }
      ```
      
      ### Python SDK
      
      ```python
      posts = client.tiktok.get_posts_by_user(
          "charlidamelio",
          identifier_type="username",
          fields=["id", "description", "like_count", "play_count", "created_at_date", "hashtags"],
          start_date="2025-01-01"
      )
      ```
      
      ### TypeScript SDK
      
      ```typescript
      const posts = await client.tiktok.getPostsByUser("charlidamelio", {
        identifierType: "username",
        fields: ["id", "description", "likeCount", "playCount", "createdAtDate", "hashtags"],
        startDate: "2025-01-01",
      });
      ```
      
      ### CLI
      
      ```bash
      xpoz-cli tiktok get_posts_by_user charlidamelio \
        --identifier-type username \
        --fields id description like_count play_count created_at_date hashtags \
        --start-date 2025-01-01
      ```
      
      ---
      
      ## getTiktokPostsByKeywords
      
      Search TikTok posts by keywords in post descriptions. Supports boolean query syntax.
      
      ### Parameters
      
      | Parameter | Type | Required | Default | Description |
      |-----------|------|----------|---------|-------------|
      | `query` | string | Yes | -- | Keyword query (supports boolean syntax) |
      | `fields` | string[] | No | `["id", "description", "username", "createdAtDate"]` | Fields to return |
      | `startDate` | string | No | -- | Start date (YYYY-MM-DD) |
      | `endDate` | string | No | -- | End date (YYYY-MM-DD) |
      | `forceLatest` | boolean | No | false | Bypass cache for fresh data |
      | `responseType` | `"fast"` \| `"paging"` \| `"csv"` | No | `"fast"` | Response mode |
      | `limit` | number | No | -- | Max results (fast mode) |
      | `pageNumber` | number | No | -- | Page to fetch (paging mode, 1-indexed) |
      | `pageNumberEnd` | number | No | -- | Last page to fetch (bulk paging) |
      | `tableName` | string | No | -- | Cached table from previous page request |
      
      ### MCP
      
      ```json
      {
        "tool": "getTiktokPostsByKeywords",
        "arguments": {
          "query": "\"AI\" AND \"productivity\"",
          "fields": ["id", "description", "username", "likeCount", "playCount", "createdAtDate"],
          "startDate": "2025-06-01",
          "endDate": "2025-06-10"
        }
      }
      ```
      
      ### Python SDK
      
      ```python
      posts = client.tiktok.search_posts(
          '"AI" AND "productivity"',
          fields=["id", "description", "username", "like_count", "play_count", "created_at_date"],
          start_date="2025-06-01",
          end_date="2025-06-10"
      )
      ```
      
      ### TypeScript SDK
      
      ```typescript
      const posts = await client.tiktok.searchPosts('"AI" AND "productivity"', {
        fields: ["id", "description", "username", "likeCount", "playCount", "createdAtDate"],
        startDate: "2025-06-01",
        endDate: "2025-06-10",
      });
      ```
      
      ### CLI
      
      ```bash
      xpoz-cli tiktok search_posts '"AI" AND "productivity"' \
        --fields id description username like_count play_count created_at_date \
        --start-date 2025-06-01 \
        --end-date 2025-06-10
      ```
      
      ---
      
      ## getTiktokPostsByHashtags
      
      > **UNIQUE TO TIKTOK** -- This tool has no equivalent on other platforms.
      
      Search TikTok posts by hashtags. Searches the indexed `hashtags` column directly, not post descriptions.
      
      ### Parameters
      
      | Parameter | Type | Required | Default | Description |
      |-----------|------|----------|---------|-------------|
      | `hashtags` | string[] | Yes | -- | 1-5 bare alphanumeric tags (no `#` prefix) |
      | `fields` | string[] | No | `["id", "description", "username", "createdAtDate"]` | Fields to return |
      | `startDate` | string | No | -- | Start date (YYYY-MM-DD) |
      | `endDate` | string | No | -- | End date (YYYY-MM-DD) |
      | `forceLatest` | boolean | No | false | Bypass cache for fresh data |
      | `responseType` | `"fast"` \| `"paging"` \| `"csv"` | No | `"fast"` | Response mode |
      | `limit` | number | No | -- | Max results (fast mode) |
      | `pageNumber` | number | No | -- | Page to fetch (paging mode, 1-indexed) |
      | `pageNumberEnd` | number | No | -- | Last page to fetch (bulk paging) |
      | `tableName` | string | No | -- | Cached table from previous page request |
      
      ### Hashtag rules
      
      - Pass bare strings: `["fyp", "cooking"]`, not `["#fyp", "#cooking"]`
      - Alphanumeric and underscores only
      - 1-5 hashtags per request
      - OR semantics: matches posts tagged with ANY of the listed hashtags
      
      ### When to use
      
      - You want posts tagged with specific TikTok hashtags
      - You are tracking hashtag trends or challenges
      - You want to analyze content within a hashtag
      
      For keyword/phrase search in post descriptions, use `getTiktokPostsByKeywords` instead.
      
      ### MCP
      
      ```json
      {
        "tool": "getTiktokPostsByHashtags",
        "arguments": {
          "hashtags": ["booktok", "reading"],
          "fields": ["id", "description", "username", "likeCount", "playCount", "createdAtDate", "hashtags"],
          "startDate": "2025-01-01"
        }
      }
      ```
      
      ### Python SDK
      
      ```python
      posts = client.tiktok.get_posts_by_hashtags(
          ["booktok", "reading"],
          fields=["id", "description", "username", "like_count", "play_count", "created_at_date", "hashtags"],
          start_date="2025-01-01"
      )
      ```
      
      ### TypeScript SDK
      
      ```typescript
      const posts = await client.tiktok.getPostsByHashtags(["booktok", "reading"], {
        fields: ["id", "description", "username", "likeCount", "playCount", "createdAtDate", "hashtags"],
        startDate: "2025-01-01",
      });
      ```
      
      ### CLI
      
      ```bash
      xpoz-cli tiktok get_posts_by_hashtags \
        --hashtags booktok reading \
        --fields id description username like_count play_count created_at_date hashtags \
        --start-date 2025-01-01
      ```
      
      ---
      
      ## getTiktokCommentsByPostId
      
      Get comments on a TikTok post. Searches the database first, then falls back to the external API for stale data (>1 week).
      
      ### Parameters
      
      | Parameter | Type | Required | Default | Description |
      |-----------|------|----------|---------|-------------|
      | `postId` | string | Yes | -- | TikTok post ID |
      | `fields` | string[] | No | `["id", "text", "username", "createdAtDate"]` | Fields to return (see Comment Fields above) |
      | `startDate` | string | No | -- | Start date (YYYY-MM-DD) |
      | `endDate` | string | No | -- | End date (YYYY-MM-DD) |
      | `forceLatest` | boolean | No | false | Bypass cache for fresh data |
      | `responseType` | `"fast"` \| `"paging"` \| `"csv"` | No | `"fast"` | Response mode |
      | `limit` | number | No | -- | Max results (fast mode) |
      | `pageNumber` | number | No | -- | Page to fetch (paging mode, 1-indexed) |
      | `pageNumberEnd` | number | No | -- | Last page to fetch (bulk paging) |
      | `tableName` | string | No | -- | Cached table from previous page request |
      
      ### MCP
      
      ```json
      {
        "tool": "getTiktokCommentsByPostId",
        "arguments": {
          "postId": "7234567890123456789",
          "fields": ["id", "text", "username", "createdAtDate", "likeCount"]
        }
      }
      ```
      
      ### Python SDK
      
      ```python
      comments = client.tiktok.get_comments(
          "7234567890123456789",
          fields=["id", "text", "username", "created_at_date", "like_count"]
      )
      ```
      
      ### TypeScript SDK
      
      ```typescript
      const comments = await client.tiktok.getComments("7234567890123456789", {
        fields: ["id", "text", "username", "createdAtDate", "likeCount"],
      });
      ```
      
      ### CLI
      
      ```bash
      xpoz-cli tiktok get_comments \
        --post-id 7234567890123456789 \
        --fields id text username created_at_date like_count
      ```
      
      ---
      
      ## Data Freshness
      
      | Data Type | Cache Threshold | Behavior |
      |-----------|----------------|----------|
      | Posts (by ID) | >3 days | DB first, API fallback if stale or missing |
      | Posts (by user) | >1 week | DB first, API fallback if stale |
      | Comments | >1 week | DB first, API fallback if stale |
      
      Use `forceLatest: true` to bypass the cache and always fetch from the external API (increases latency and cost).
      
      ## Response Modes
      
      All paginated tools (`getTiktokUsersByKeywords`, `getTiktokUsersByHashtags`, `getTiktokPostsByUser`, `getTiktokPostsByKeywords`, `getTiktokPostsByHashtags`, `getTiktokCommentsByPostId`) support three response modes:
      
      | Mode | Behavior | Best For |
      |------|----------|----------|
      | `"fast"` (default) | Returns up to 300 results immediately | Quick lookups, exploration |
      | `"paging"` | Async, returns `operationId` -- poll with `checkOperationStatus` | Large datasets, page-by-page (100/page) |
      | `"csv"` | Async CSV export to S3 -- returns download URL | Bulk export, offline analysis |
      
      ### Paging workflow
      
      1. First call: omit `pageNumber` and `tableName`. Returns page 1 with `tableName`, `totalPages`, `totalRows`.
      2. Subsequent pages: pass `tableName` from step 1 with `pageNumber` (2, 3, ...).
      3. Bulk fetch: pass `pageNumber` + `pageNumberEnd` + `tableName` to get multiple consecutive pages.
      
    • twitter.md 22.4 KB
      # Twitter/X Tools Reference
      
      ## Table of Contents
      
      - [User Tools](#user-tools)
        - [getTwitterUser](#getTwitterUser)
        - [getTwitterUsers](#getTwitterUsers)
        - [searchTwitterUsers](#searchTwitterUsers)
        - [getTwitterUserConnections](#getTwitterUserConnections)
        - [getTwitterUsersByKeywords](#getTwitterUsersByKeywords)
      - [Post Tools](#post-tools)
        - [getTwitterPostsByIds](#getTwitterPostsByIds)
        - [getTwitterPostsByAuthor](#getTwitterPostsByAuthor)
        - [getTwitterPostsByKeywords](#getTwitterPostsByKeywords)
        - [getTwitterPostRetweets](#getTwitterPostRetweets)
        - [getTwitterPostQuotes](#getTwitterPostQuotes)
        - [getTwitterPostComments](#getTwitterPostComments)
        - [getTwitterPostInteractingUsers](#getTwitterPostInteractingUsers)
        - [countTweets](#countTweets)
      
      ---
      
      ## User Fields
      
      These fields are available on all user-returning tools:
      
      `id`, `username`, `name`, `description`, `location`, `verified`, `followersCount`, `followingCount`, `tweetCount`, `profileImageUrl`, `createdAt`
      
      ## Post Fields
      
      These fields are available on all post-returning tools:
      
      `id`, `text`, `authorId`, `authorUsername`, `createdAt`, `createdAtDate`, `likeCount`, `retweetCount`, `replyCount`, `quoteCount`, `impressionCount`, `bookmarkCount`, `lang`, `isRetweet`, `isReply`, `hashtags`, `mentions`, `mediaUrls`, `country`, `region`, `city`
      
      ---
      
      ## User Tools
      
      ### getTwitterUser
      
      Get a single Twitter user by ID or username.
      
      #### Parameters
      
      | Parameter | Type | Required | Description |
      |-----------|------|----------|-------------|
      | `identifier` | string | Yes | The user ID or username to look up |
      | `identifierType` | `"id"` \| `"username"` | Yes | Whether `identifier` is an ID or username |
      | `fields` | string[] | No | Fields to return (see [User Fields](#user-fields)) |
      
      #### Examples
      
      **MCP:**
      ```json
      {
        "tool": "getTwitterUser",
        "arguments": {
          "identifier": "elonmusk",
          "identifierType": "username",
          "fields": ["id", "username", "name", "followersCount", "verified"]
        }
      }
      ```
      
      **Python SDK:**
      ```python
      user = client.twitter.get_user(
          "elonmusk",
          identifier_type="username",
          fields=["id", "username", "name", "followers_count", "verified"]
      )
      ```
      
      **TypeScript SDK:**
      ```typescript
      const user = await client.twitter.getUser("elonmusk", {
        identifierType: "username",
        fields: ["id", "username", "name", "followersCount", "verified"],
      });
      ```
      
      **CLI:**
      ```bash
      xpoz-cli twitter get_user --identifier elonmusk --identifier-type username --fields id username name followers_count verified
      ```
      
      ---
      
      ### getTwitterUsers
      
      Get 1-100 Twitter users by IDs or usernames in a single call.
      
      #### Parameters
      
      | Parameter | Type | Required | Description |
      |-----------|------|----------|-------------|
      | `identifiers` | string[] | Yes | 1-100 user IDs or usernames |
      | `identifierType` | `"id"` \| `"username"` | Yes | Whether identifiers are IDs or usernames |
      | `fields` | string[] | No | Fields to return (see [User Fields](#user-fields)) |
      | `forceLatest` | boolean | No | Bypass cache and fetch fresh data from API |
      
      #### Examples
      
      **MCP:**
      ```json
      {
        "tool": "getTwitterUsers",
        "arguments": {
          "identifiers": ["elonmusk", "sama", "kaborofficial"],
          "identifierType": "username",
          "fields": ["id", "username", "name", "followersCount"]
        }
      }
      ```
      
      **Python SDK:**
      ```python
      users = client.twitter.get_users(
          ["elonmusk", "sama", "kaborofficial"],
          identifier_type="username",
          fields=["id", "username", "name", "followers_count"]
      )
      ```
      
      **TypeScript SDK:**
      ```typescript
      const users = await client.twitter.getUsers(
        ["elonmusk", "sama", "kaborofficial"],
        {
          identifierType: "username",
          fields: ["id", "username", "name", "followersCount"],
        }
      );
      ```
      
      **CLI:**
      ```bash
      xpoz-cli twitter get_users --identifiers elonmusk sama kaborofficial --identifier-type username --fields id username name followers_count
      ```
      
      ---
      
      ### searchTwitterUsers
      
      Search for Twitter users by name or username via fuzzy matching.
      
      #### Parameters
      
      | Parameter | Type | Required | Description |
      |-----------|------|----------|-------------|
      | `name` | string | Yes | Name or username to search for |
      | `limit` | number | No | Max results to return (default 10, max 10) |
      | `fields` | string[] | No | Fields to return (see [User Fields](#user-fields)) |
      
      #### Examples
      
      **MCP:**
      ```json
      {
        "tool": "searchTwitterUsers",
        "arguments": {
          "name": "Elon",
          "limit": 5,
          "fields": ["id", "username", "name", "followersCount"]
        }
      }
      ```
      
      **Python SDK:**
      ```python
      users = client.twitter.search_users(
          "Elon",
          limit=5,
          fields=["id", "username", "name", "followers_count"]
      )
      ```
      
      **TypeScript SDK:**
      ```typescript
      const users = await client.twitter.searchUsers("Elon", {
        limit: 5,
        fields: ["id", "username", "name", "followersCount"],
      });
      ```
      
      **CLI:**
      ```bash
      xpoz-cli twitter search_users --name Elon --limit 5 --fields id username name followers_count
      ```
      
      ---
      
      ### getTwitterUserConnections
      
      Get followers or following list for a Twitter user.
      
      #### Parameters
      
      | Parameter | Type | Required | Description |
      |-----------|------|----------|-------------|
      | `username` | string | Yes | Twitter username (without @) |
      | `connectionType` | `"followers"` \| `"following"` | Yes | Type of connection to retrieve |
      | `fields` | string[] | No | Fields to return (see [User Fields](#user-fields)) |
      | `forceLatest` | boolean | No | Bypass cache and fetch fresh data from API |
      | `responseType` | `"fast"` \| `"paging"` \| `"csv"` | No | Response mode (default `"fast"`) |
      | `limit` | number | No | Max results to return |
      | `pageNumber` | number | No | Page number for paging mode |
      | `pageNumberEnd` | number | No | End page for paging mode |
      | `tableName` | string | No | Table name for paging mode (from operation result) |
      
      #### Response Modes
      
      | Mode | Behavior |
      |------|----------|
      | `"fast"` | Returns up to 300 results immediately |
      | `"paging"` | Async operation -- returns `operationId`, poll with `checkOperationStatus` |
      | `"csv"` | Async CSV export -- returns download URL when complete |
      
      #### Examples
      
      **MCP:**
      ```json
      {
        "tool": "getTwitterUserConnections",
        "arguments": {
          "username": "elonmusk",
          "connectionType": "followers",
          "fields": ["id", "username", "name", "followersCount"],
          "responseType": "fast"
        }
      }
      ```
      
      **Python SDK:**
      ```python
      followers = client.twitter.get_user_connections(
          "elonmusk",
          connection_type="followers",
          fields=["id", "username", "name", "followers_count"]
      )
      ```
      
      **TypeScript SDK:**
      ```typescript
      const followers = await client.twitter.getUserConnections(
        "elonmusk",
        "followers",
        {
          fields: ["id", "username", "name", "followersCount"],
        }
      );
      ```
      
      **CLI:**
      ```bash
      xpoz-cli twitter get_user_connections --username elonmusk --connection-type followers --fields id username name followers_count --response-type fast
      ```
      
      ---
      
      ### getTwitterUsersByKeywords
      
      Find Twitter users who posted content matching keywords. Returns users aggregated from matching posts.
      
      #### Parameters
      
      | Parameter | Type | Required | Description |
      |-----------|------|----------|-------------|
      | `query` | string | Yes | Keyword query (supports boolean operators) |
      | `fields` | string[] | No | Fields to return (see [User Fields](#user-fields) plus aggregate fields below) |
      | `startDate` | string | No | Start date in YYYY-MM-DD format |
      | `endDate` | string | No | End date in YYYY-MM-DD format |
      | `language` | string | No | ISO language code (e.g., `"en"`) |
      | `forceLatest` | boolean | No | Bypass cache and fetch fresh data from API |
      | `responseType` | `"fast"` \| `"paging"` \| `"csv"` | No | Response mode (default `"fast"`) |
      | `limit` | number | No | Max results to return |
      | `pageNumber` | number | No | Page number for paging mode |
      | `pageNumberEnd` | number | No | End page for paging mode |
      | `tableName` | string | No | Table name for paging mode (from operation result) |
      
      #### Aggregate Fields
      
      These fields must be explicitly requested in the `fields` array:
      
      `aggRelevance`, `relevantTweetsCount`, `relevantTweetsImpressionsSum`, `relevantTweetsLikesSum`, `relevantTweetsQuotesSum`, `relevantTweetsRepliesSum`, `relevantTweetsRetweetsSum`
      
      #### Examples
      
      **MCP:**
      ```json
      {
        "tool": "getTwitterUsersByKeywords",
        "arguments": {
          "query": "\"artificial intelligence\" AND safety",
          "fields": ["id", "username", "name", "followersCount", "aggRelevance", "relevantTweetsCount"],
          "startDate": "2026-01-01",
          "endDate": "2026-06-10",
          "language": "en"
        }
      }
      ```
      
      **Python SDK:**
      ```python
      users = client.twitter.get_users_by_keywords(
          "\"artificial intelligence\" AND safety",
          fields=["id", "username", "name", "followers_count", "agg_relevance", "relevant_tweets_count"],
          start_date="2026-01-01",
          end_date="2026-06-10",
          language="en"
      )
      ```
      
      **TypeScript SDK:**
      ```typescript
      const users = await client.twitter.getUsersByKeywords(
        '"artificial intelligence" AND safety',
        {
          fields: ["id", "username", "name", "followersCount", "aggRelevance", "relevantTweetsCount"],
          startDate: "2026-01-01",
          endDate: "2026-06-10",
          language: "en",
        }
      );
      ```
      
      **CLI:**
      ```bash
      xpoz-cli twitter get_users_by_keywords --query '"artificial intelligence" AND safety' --fields id username name followers_count agg_relevance relevant_tweets_count --start-date 2026-01-01 --end-date 2026-06-10 --language en
      ```
      
      ---
      
      ## Post Tools
      
      ### getTwitterPostsByIds
      
      Get 1-100 Twitter posts by their numeric IDs.
      
      #### Parameters
      
      | Parameter | Type | Required | Description |
      |-----------|------|----------|-------------|
      | `postIds` | string[] | Yes | 1-100 numeric post IDs |
      | `fields` | string[] | No | Fields to return (see [Post Fields](#post-fields)) |
      | `forceLatest` | boolean | No | Bypass cache and fetch fresh data from API |
      
      #### Examples
      
      **MCP:**
      ```json
      {
        "tool": "getTwitterPostsByIds",
        "arguments": {
          "postIds": ["1234567890123456789", "9876543210987654321"],
          "fields": ["id", "text", "authorUsername", "retweetCount", "impressionCount"]
        }
      }
      ```
      
      **Python SDK:**
      ```python
      posts = client.twitter.get_posts_by_ids(
          ["1234567890123456789", "9876543210987654321"],
          fields=["id", "text", "author_username", "retweet_count", "impression_count"]
      )
      ```
      
      **TypeScript SDK:**
      ```typescript
      const posts = await client.twitter.getPostsByIds(
        ["1234567890123456789", "9876543210987654321"],
        {
          fields: ["id", "text", "authorUsername", "retweetCount", "impressionCount"],
        }
      );
      ```
      
      **CLI:**
      ```bash
      xpoz-cli twitter get_posts_by_ids --post-ids 1234567890123456789 9876543210987654321 --fields id text author_username retweet_count impression_count
      ```
      
      ---
      
      ### getTwitterPostsByAuthor
      
      Get posts from a Twitter user by their username.
      
      #### Parameters
      
      | Parameter | Type | Required | Description |
      |-----------|------|----------|-------------|
      | `username` | string | Yes | Twitter username (without @ symbol) |
      | `fields` | string[] | No | Fields to return (see [Post Fields](#post-fields); default: `id`, `text`, `authorUsername`, `createdAtDate`) |
      | `startDate` | string | No | Start date in YYYY-MM-DD format |
      | `endDate` | string | No | End date in YYYY-MM-DD format |
      | `forceLatest` | boolean | No | Bypass cache and fetch fresh data from API |
      | `responseType` | `"fast"` \| `"paging"` \| `"csv"` | No | Response mode (default `"fast"`) |
      | `limit` | number | No | Max results to return |
      | `pageNumber` | number | No | Page number for paging mode |
      | `pageNumberEnd` | number | No | End page for paging mode |
      | `tableName` | string | No | Table name for paging mode (from operation result) |
      
      #### Examples
      
      **MCP:**
      ```json
      {
        "tool": "getTwitterPostsByAuthor",
        "arguments": {
          "username": "sama",
          "fields": ["id", "text", "createdAtDate", "retweetCount", "impressionCount"],
          "startDate": "2026-01-01",
          "endDate": "2026-06-10"
        }
      }
      ```
      
      **Python SDK:**
      ```python
      posts = client.twitter.get_posts_by_author(
          "sama",
          fields=["id", "text", "created_at_date", "retweet_count", "impression_count"],
          start_date="2026-01-01",
          end_date="2026-06-10"
      )
      ```
      
      **TypeScript SDK:**
      ```typescript
      const posts = await client.twitter.getPostsByAuthor("sama", {
        fields: ["id", "text", "createdAtDate", "retweetCount", "impressionCount"],
        startDate: "2026-01-01",
        endDate: "2026-06-10",
      });
      ```
      
      **CLI:**
      ```bash
      xpoz-cli twitter get_posts_by_author --username sama --fields id text created_at_date retweet_count impression_count --start-date 2026-01-01 --end-date 2026-06-10
      ```
      
      ---
      
      ### getTwitterPostsByKeywords
      
      Search Twitter posts by keywords with boolean query support.
      
      #### Parameters
      
      | Parameter | Type | Required | Description |
      |-----------|------|----------|-------------|
      | `query` | string | Yes | Keyword query (supports boolean operators: AND, OR, NOT, exact phrases, grouping) |
      | `fields` | string[] | No | Fields to return (see [Post Fields](#post-fields); default: `id`, `text`, `authorUsername`, `createdAtDate`) |
      | `startDate` | string | No | Start date in YYYY-MM-DD format |
      | `endDate` | string | No | End date in YYYY-MM-DD format |
      | `authorUsername` | string | No | Filter to posts by this username |
      | `authorId` | string | No | Filter to posts by this user ID |
      | `language` | string | No | ISO language code (e.g., `"en"`) |
      | `filterOutRetweets` | boolean | No | Exclude retweets from results |
      | `forceLatest` | boolean | No | Bypass cache and fetch fresh data from API |
      | `responseType` | `"fast"` \| `"paging"` \| `"csv"` | No | Response mode (default `"fast"`) |
      | `limit` | number | No | Max results to return |
      | `pageNumber` | number | No | Page number for paging mode |
      | `pageNumberEnd` | number | No | End page for paging mode |
      | `tableName` | string | No | Table name for paging mode (from operation result) |
      
      #### Examples
      
      **MCP:**
      ```json
      {
        "tool": "getTwitterPostsByKeywords",
        "arguments": {
          "query": "(\"machine learning\" OR \"deep learning\") AND python",
          "fields": ["id", "text", "authorUsername", "createdAtDate", "retweetCount", "lang"],
          "startDate": "2026-05-01",
          "endDate": "2026-06-10",
          "language": "en",
          "filterOutRetweets": true
        }
      }
      ```
      
      **Python SDK:**
      ```python
      posts = client.twitter.search_posts(
          "(\"machine learning\" OR \"deep learning\") AND python",
          fields=["id", "text", "author_username", "created_at_date", "retweet_count", "lang"],
          start_date="2026-05-01",
          end_date="2026-06-10",
          language="en",
          filter_out_retweets=True
      )
      ```
      
      **TypeScript SDK:**
      ```typescript
      const posts = await client.twitter.searchPosts(
        '("machine learning" OR "deep learning") AND python',
        {
          fields: ["id", "text", "authorUsername", "createdAtDate", "retweetCount", "lang"],
          startDate: "2026-05-01",
          endDate: "2026-06-10",
          language: "en",
          filterOutRetweets: true,
        }
      );
      ```
      
      **CLI:**
      ```bash
      xpoz-cli twitter search_posts --query '("machine learning" OR "deep learning") AND python' --fields id text author_username created_at_date retweet_count lang --start-date 2026-05-01 --end-date 2026-06-10 --language en --filter-out-retweets
      ```
      
      ---
      
      ### getTwitterPostRetweets
      
      Get retweets of a specific post. Database-only lookup with no API fallback.
      
      #### Parameters
      
      | Parameter | Type | Required | Description |
      |-----------|------|----------|-------------|
      | `postId` | string | Yes | Numeric ID of the original post |
      | `fields` | string[] | No | Fields to return (see [Post Fields](#post-fields)) |
      | `startDate` | string | No | Start date in YYYY-MM-DD format |
      | `endDate` | string | No | End date in YYYY-MM-DD format |
      | `responseType` | `"fast"` \| `"paging"` | No | Response mode (default `"fast"`; CSV not supported) |
      | `limit` | number | No | Max results to return |
      | `pageNumber` | number | No | Page number for paging mode |
      | `pageNumberEnd` | number | No | End page for paging mode |
      | `tableName` | string | No | Table name for paging mode (from operation result) |
      
      #### Examples
      
      **MCP:**
      ```json
      {
        "tool": "getTwitterPostRetweets",
        "arguments": {
          "postId": "1234567890123456789",
          "fields": ["id", "text", "authorUsername", "createdAtDate"]
        }
      }
      ```
      
      **Python SDK:**
      ```python
      retweets = client.twitter.get_retweets(
          "1234567890123456789",
          fields=["id", "text", "author_username", "created_at_date"]
      )
      ```
      
      **TypeScript SDK:**
      ```typescript
      const retweets = await client.twitter.getRetweets("1234567890123456789", {
        fields: ["id", "text", "authorUsername", "createdAtDate"],
      });
      ```
      
      **CLI:**
      ```bash
      xpoz-cli twitter get_retweets --post-id 1234567890123456789 --fields id text author_username created_at_date
      ```
      
      ---
      
      ### getTwitterPostQuotes
      
      Get quote tweets of a specific post. Refreshes from API if data is stale (>10 days).
      
      #### Parameters
      
      | Parameter | Type | Required | Description |
      |-----------|------|----------|-------------|
      | `postId` | string | Yes | Numeric ID of the original post |
      | `fields` | string[] | No | Fields to return (see [Post Fields](#post-fields)) |
      | `startDate` | string | No | Start date in YYYY-MM-DD format |
      | `forceLatest` | boolean | No | Bypass cache and fetch fresh data from API |
      | `responseType` | `"fast"` \| `"paging"` \| `"csv"` | No | Response mode (default `"fast"`) |
      | `limit` | number | No | Max results to return |
      | `pageNumber` | number | No | Page number for paging mode |
      | `pageNumberEnd` | number | No | End page for paging mode |
      | `tableName` | string | No | Table name for paging mode (from operation result) |
      
      #### Examples
      
      **MCP:**
      ```json
      {
        "tool": "getTwitterPostQuotes",
        "arguments": {
          "postId": "1234567890123456789",
          "fields": ["id", "text", "authorUsername", "createdAtDate", "impressionCount"],
          "forceLatest": true
        }
      }
      ```
      
      **Python SDK:**
      ```python
      quotes = client.twitter.get_quotes(
          "1234567890123456789",
          fields=["id", "text", "author_username", "created_at_date", "impression_count"],
          force_latest=True
      )
      ```
      
      **TypeScript SDK:**
      ```typescript
      const quotes = await client.twitter.getQuotes("1234567890123456789", {
        fields: ["id", "text", "authorUsername", "createdAtDate", "impressionCount"],
        forceLatest: true,
      });
      ```
      
      **CLI:**
      ```bash
      xpoz-cli twitter get_quotes --post-id 1234567890123456789 --fields id text author_username created_at_date impression_count --force-latest
      ```
      
      ---
      
      ### getTwitterPostComments
      
      Get replies to a specific post. Refreshes from API if data is stale (>10 days).
      
      #### Parameters
      
      | Parameter | Type | Required | Description |
      |-----------|------|----------|-------------|
      | `postId` | string | Yes | Numeric ID of the post |
      | `fields` | string[] | No | Fields to return (see [Post Fields](#post-fields)) |
      | `startDate` | string | No | Start date in YYYY-MM-DD format |
      | `forceLatest` | boolean | No | Bypass cache and fetch fresh data from API |
      | `responseType` | `"fast"` \| `"paging"` \| `"csv"` | No | Response mode (default `"fast"`) |
      | `limit` | number | No | Max results to return |
      | `pageNumber` | number | No | Page number for paging mode |
      | `pageNumberEnd` | number | No | End page for paging mode |
      | `tableName` | string | No | Table name for paging mode (from operation result) |
      
      #### Examples
      
      **MCP:**
      ```json
      {
        "tool": "getTwitterPostComments",
        "arguments": {
          "postId": "1234567890123456789",
          "fields": ["id", "text", "authorUsername", "createdAtDate"],
          "forceLatest": true
        }
      }
      ```
      
      **Python SDK:**
      ```python
      comments = client.twitter.get_comments(
          "1234567890123456789",
          fields=["id", "text", "author_username", "created_at_date"],
          force_latest=True
      )
      ```
      
      **TypeScript SDK:**
      ```typescript
      const comments = await client.twitter.getComments("1234567890123456789", {
        fields: ["id", "text", "authorUsername", "createdAtDate"],
        forceLatest: true,
      });
      ```
      
      **CLI:**
      ```bash
      xpoz-cli twitter get_comments --post-id 1234567890123456789 --fields id text author_username created_at_date --force-latest
      ```
      
      ---
      
      ### getTwitterPostInteractingUsers
      
      Get users who interacted with a specific post by commenting, quoting, or retweeting.
      
      #### Parameters
      
      | Parameter | Type | Required | Description |
      |-----------|------|----------|-------------|
      | `postId` | string | Yes | Numeric ID of the post |
      | `interactionType` | `"commenters"` \| `"quoters"` \| `"retweeters"` | Yes | Type of interaction to retrieve |
      | `fields` | string[] | No | Fields to return (see [User Fields](#user-fields)) |
      | `startDate` | string | No | Start date in YYYY-MM-DD format |
      | `endDate` | string | No | End date in YYYY-MM-DD format |
      | `forceLatest` | boolean | No | Bypass cache and fetch fresh data from API |
      | `responseType` | `"fast"` \| `"paging"` \| `"csv"` | No | Response mode (default `"fast"`) |
      | `limit` | number | No | Max results to return |
      | `pageNumber` | number | No | Page number for paging mode |
      | `pageNumberEnd` | number | No | End page for paging mode |
      | `tableName` | string | No | Table name for paging mode (from operation result) |
      
      #### Examples
      
      **MCP:**
      ```json
      {
        "tool": "getTwitterPostInteractingUsers",
        "arguments": {
          "postId": "1234567890123456789",
          "interactionType": "commenters",
          "fields": ["id", "username", "name", "followersCount"]
        }
      }
      ```
      
      **Python SDK:**
      ```python
      users = client.twitter.get_post_interacting_users(
          "1234567890123456789",
          interaction_type="commenters",
          fields=["id", "username", "name", "followers_count"]
      )
      ```
      
      **TypeScript SDK:**
      ```typescript
      const users = await client.twitter.getPostInteractingUsers(
        "1234567890123456789",
        "commenters",
        {
          fields: ["id", "username", "name", "followersCount"],
        }
      );
      ```
      
      **CLI:**
      ```bash
      xpoz-cli twitter get_post_interacting_users --post-id 1234567890123456789 --interaction-type commenters --fields id username name followers_count
      ```
      
      ---
      
      ### countTweets
      
      Count tweets matching a phrase over a date range. Returns a single number.
      
      #### Parameters
      
      | Parameter | Type | Required | Description |
      |-----------|------|----------|-------------|
      | `phrase` | string | Yes | Phrase to count tweets for |
      | `startDate` | string | No | Start date in YYYY-MM-DD format (default: 6 months ago) |
      | `endDate` | string | No | End date in YYYY-MM-DD format (default: today) |
      
      #### Examples
      
      **MCP:**
      ```json
      {
        "tool": "countTweets",
        "arguments": {
          "phrase": "artificial intelligence",
          "startDate": "2026-01-01",
          "endDate": "2026-06-10"
        }
      }
      ```
      
      **Python SDK:**
      ```python
      count = client.twitter.count_posts(
          "artificial intelligence",
          start_date="2026-01-01",
          end_date="2026-06-10"
      )
      # count is an int
      print(f"Found {count:,} tweets")
      ```
      
      **TypeScript SDK:**
      ```typescript
      const count = await client.twitter.countPosts("artificial intelligence", {
        startDate: "2026-01-01",
        endDate: "2026-06-10",
      });
      // count is a number
      console.log(`Found ${count.toLocaleString()} tweets`);
      ```
      
      **CLI:**
      ```bash
      xpoz-cli twitter count_posts --phrase "artificial intelligence" --start-date 2026-01-01 --end-date 2026-06-10
      ```
      
  • SKILL.md 12.1 KB
    ---
    name: xpoz-best-practices
    version: 2026-06-10
    description: Reference guide for using Xpoz effectively. Load this skill whenever working with Xpoz MCP tools, SDKs, or CLI — it ensures correct query syntax, optimal field selection, proper pagination, and best practices for every Xpoz interaction. Covers authentication, query syntax (boolean operators, date filtering), response modes (fast/paging/CSV), field selection, tracking setup, and all platform tool references (Twitter, Instagram, Reddit, TikTok). Use for ANY Xpoz-related work, not just explicit best-practices questions.
    allowed-tools: Bash(xpoz-cli *)
    ---
    
    # Xpoz Best Practices
    
    ## Overview
    
    Xpoz is a social media intelligence platform providing access to **Twitter/X**, **Instagram**, **Reddit**, and **TikTok** data through MCP tools, Python SDK, TypeScript SDK, and CLI — no social media API keys required.
    
    
    ## When to Use
    
    Load this skill for **any Xpoz interaction** — not just when the user explicitly asks about best practices. It provides the context needed to use Xpoz tools correctly:
    
    - Calling any Xpoz MCP tool (query syntax, field selection, response modes)
    - Writing code with the Python or TypeScript SDK
    - Using the Xpoz CLI
    - Setting up authentication or tracking
    - Troubleshooting errors or empty results
    - Choosing which tool to use for a specific task
    
    ## Quick Start
    
    **MCP** — add the Xpoz MCP server to your agent's config. The server URL is `https://mcp.xpoz.ai/mcp`. Most MCP clients handle OAuth automatically on first tool call.
    
    Example for Claude Code (`~/.claude.json`):
    ```json
    {
      "mcpServers": {
        "xpoz": {
          "url": "https://mcp.xpoz.ai/mcp",
          "transport": "streamable-http"
        }
      }
    }
    ```
    
    **Python SDK:**
    ```bash
    pip install xpoz
    ```
    ```python
    from xpoz import XpozClient
    client = XpozClient()  # reads XPOZ_API_KEY env var
    results = client.twitter.search_posts("artificial intelligence")
    print(f"Found {results.pagination.total_rows:,} tweets")
    client.close()
    ```
    
    **TypeScript SDK:**
    ```bash
    npm install @xpoz/xpoz
    ```
    ```typescript
    import { XpozClient } from "@xpoz/xpoz";
    const client = new XpozClient();
    await client.connect();
    const results = await client.twitter.searchPosts("artificial intelligence");
    console.log(`Found ${results.pagination.totalRows.toLocaleString()} tweets`);
    await client.close();
    ```
    
    **CLI:**
    ```bash
    pip install xpoz-cli
    xpoz-cli twitter search_posts --query "artificial intelligence" --limit 20
    ```
    
    See **[references/authentication.md](references/authentication.md)** for detailed auth flows (MCP, SDK, CLI).
    See **[references/sdk.md](references/sdk.md)** for complete Python & TypeScript SDK reference.
    See **[references/cli.md](references/cli.md)** for CLI installation, commands, and rendering modes.
    
    ## Query Syntax
    
    All keyword search tools support boolean query syntax:
    
    | Operator | Example | Effect |
    |----------|---------|--------|
    | Exact phrase | `"machine learning"` | Matches exact phrase |
    | OR | `"AI" OR "artificial intelligence"` | Matches either term |
    | AND | `"Tesla" AND "earnings"` | Matches both terms |
    | Grouping | `("deep learning" OR "neural network") AND python` | Combines operators |
    
    **Date filtering:** Use `startDate` / `endDate` in YYYY-MM-DD format. Omit to use defaults (varies by tool).
    
    **Content filtering** (Twitter only): Set `filterOutRetweets: true` to exclude retweets.
    
    **Forbidden in query string:** `from:`, `to:`, `lang:`, `since:`, `until:`, `filter:` — use dedicated parameters instead.
    
    ## Platform Quick Reference
    
    ### Twitter/X (13 tools)
    | Tool | Purpose |
    |------|---------|
    | `getTwitterUser` / `getTwitterUsers` | Look up 1-100 users by ID or username |
    | `searchTwitterUsers` | Fuzzy search users by name |
    | `getTwitterUserConnections` | Get followers or following |
    | `getTwitterUsersByKeywords` | Find users who posted about a topic |
    | `getTwitterPostsByIds` | Get 1-100 posts by ID |
    | `getTwitterPostsByAuthor` | Get all posts from a username |
    | `getTwitterPostsByKeywords` | Search posts by keywords |
    | `getTwitterPostRetweets` | Get retweets of a post |
    | `getTwitterPostQuotes` | Get quote tweets of a post |
    | `getTwitterPostComments` | Get replies to a post |
    | `getTwitterPostInteractingUsers` | Get commenters, quoters, or retweeters |
    | `countTweets` | Count tweets matching a phrase |
    
    See **[references/twitter.md](references/twitter.md)** for all parameters, fields, and examples.
    
    ### Instagram (9 tools)
    | Tool | Purpose |
    |------|---------|
    | `getInstagramUser` | Look up user by ID or username |
    | `searchInstagramUsers` | Fuzzy search users by name |
    | `getInstagramUserConnections` | Get followers or following |
    | `getInstagramUsersByKeywords` | Find users who posted about a topic |
    | `getInstagramPostInteractingUsers` | Get commenters or likers of a post |
    | `getInstagramPostsByIds` | Get posts by strong_id |
    | `getInstagramPostsByUser` | Get posts from a user |
    | `getInstagramPostsByKeywords` | Search posts by keywords in captions/subtitles |
    | `getInstagramCommentsByPostId` | Get comments on a post |
    
    See **[references/instagram.md](references/instagram.md)** for all parameters, fields, and examples.
    
    ### Reddit (9 tools)
    | Tool | Purpose |
    |------|---------|
    | `getRedditUser` | Look up user by username |
    | `searchRedditUsers` | Fuzzy search users by name |
    | `getRedditUsersByKeywords` | Find users who posted about a topic |
    | `getRedditPostsByKeywords` | Search posts by keywords |
    | `getRedditPostWithCommentsById` | Get a post with all its comments |
    | `getRedditCommentsByKeywords` | Search comments by keywords |
    | `searchRedditSubreddits` | Search subreddits by name |
    | `getRedditSubredditWithPostsByName` | Get subreddit details with posts |
    | `getRedditSubredditsByKeywords` | Search subreddits by keyword in description |
    
    See **[references/reddit.md](references/reddit.md)** for all parameters, fields, and examples.
    
    ### TikTok (9 tools)
    | Tool | Purpose |
    |------|---------|
    | `getTiktokUser` | Look up user by ID or username |
    | `searchTiktokUsers` | Fuzzy search users by name |
    | `getTiktokUsersByKeywords` | Find users who posted about a topic |
    | `getTiktokUsersByHashtags` | Find users who used specific hashtags |
    | `getTiktokPostsByIds` | Get posts by ID |
    | `getTiktokPostsByUser` | Get posts from a user |
    | `getTiktokPostsByKeywords` | Search posts by keywords |
    | `getTiktokPostsByHashtags` | Search posts by hashtags |
    | `getTiktokCommentsByPostId` | Get comments on a post |
    
    See **[references/tiktok.md](references/tiktok.md)** for all parameters, fields, and examples.
    
    ## Tracking
    
    Setting up tracking is a best practice for getting more complete data from Xpoz. Tracked items are crawled regularly in the background, which means:
    
    - **Better coverage** — continuous collection captures posts and activity that a single point-in-time query might miss
    - **More complete data** — tracked items accumulate data over time, giving you a fuller picture than one-off queries
    
    Track keywords, users, subreddits, and hashtags across all 4 platforms.
    
    **Supported types per platform:**
    
    | Platform | keyword | user | subreddit | hashtag |
    |----------|---------|------|-----------|---------|
    | Twitter | Yes | Yes | — | — |
    | Instagram | Yes | Yes | — | — |
    | Reddit | Yes | Yes | Yes | — |
    | TikTok | Yes | Yes | — | Yes |
    
    **View current tracking:**
    ```
    MCP:        call getTrackedItems
    Python:     client.tracking.get_tracked_items()
    TypeScript: await client.tracking.getTrackedItems()
    CLI:        xpoz-cli tracking get_tracked_items
    ```
    
    **Add tracked items:**
    ```
    MCP:        call addTrackedItems with items: [{ phrase: "AI agents", type: "keyword", platform: "twitter" }]
    Python:     client.tracking.add_tracked_items([{ "phrase": "AI agents", "type": "keyword", "platform": "twitter" }])
    TypeScript: await client.tracking.addTrackedItems([{ phrase: "AI agents", type: "keyword", platform: "twitter" }])
    CLI:        xpoz-cli tracking add_tracked_items --items '[{"phrase": "AI agents", "type": "keyword", "platform": "twitter"}]'
    ```
    
    **Remove tracked items:**
    ```
    MCP:        call removeTrackedItems with items: [{ phrase: "AI agents", type: "keyword", platform: "twitter" }]
    Python:     client.tracking.remove_tracked_items([...])
    TypeScript: await client.tracking.removeTrackedItems([...])
    CLI:        xpoz-cli tracking remove_tracked_items --items '[{"phrase": "AI agents", "type": "keyword", "platform": "twitter"}]'
    ```
    
    See **[xpoz-social-tracking](../xpoz-social-tracking/SKILL.md)** for full tracking workflows and advanced patterns.
    
    ## Response Modes
    
    All paginated tools support three response modes via `responseType`:
    
    | Mode | Behavior | Best For |
    |------|----------|----------|
    | `"fast"` (default) | Returns up to 300 results immediately | Quick lookups, exploration |
    | `"paging"` | Async — returns `operationId`, poll with `checkOperationStatus` | Large datasets, page-by-page |
    | `"csv"` | Async CSV export to S3 — returns download URL | Bulk export, offline analysis |
    
    See **[references/pagination-and-export.md](references/pagination-and-export.md)** for async polling patterns, pagination, and CSV export details.
    
    ## Field Selection
    
    Pass `fields` to request only the data you need. This reduces response size and improves performance.
    
    ```
    MCP:        fields: ["id", "text", "authorUsername", "likeCount"]
    Python:     fields=["id", "text", "author_username", "like_count"]
    TypeScript: fields: ["id", "text", "authorUsername", "likeCount"]
    CLI:        --fields id text author_username like_count
    ```
    
    Each platform has different available fields — see the platform-specific references for complete field lists.
    
    ## Common Patterns
    
    **Search → Analyze → Export:**
    1. Search posts by keywords (fast mode) to preview results
    2. Analyze engagement, sentiment, or themes
    3. Export full dataset to CSV for deeper analysis
    
    **Find Users → Get Their Posts → Analyze:**
    1. Search users by keywords to find relevant accounts
    2. Get posts by author for top accounts
    3. Analyze content patterns, posting frequency, engagement
    
    **Data Freshness:**
    - Data is cached in Xpoz's database with automatic API fallback when stale — results are kept fresh automatically
    - Use `forceLatest: true` to bypass cache and force a live fetch (increases latency and cost)
    
    ## Troubleshooting
    
    | Problem | Solution |
    |---------|----------|
    | MCP: "Unauthorized" | Re-run OAuth flow — see [references/authentication.md](references/authentication.md) |
    | SDK: `AuthenticationError` | Verify key at [xpoz.ai/settings](https://xpoz.ai/settings) |
    | Empty results | Check query syntax, widen date range, try different keywords |
    | Stale data | Use `forceLatest: true` to bypass cache |
    | Operation timeout | Keep polling `checkOperationStatus` every ~5s until status is no longer `running` |
    | Token exchange fails | Ask user to re-authorize — codes are single-use |
    
    ## Detailed Guides
    
    For complete parameters, response fields, patterns, and examples:
    
    - **[references/authentication.md](references/authentication.md)** — Auth flows for MCP, SDK (API key), CLI
    - **[references/sdk.md](references/sdk.md)** — Python & TypeScript SDK: setup, namespaces, pagination helpers, async patterns
    - **[references/cli.md](references/cli.md)** — CLI installation, command structure, rendering modes, examples
    - **[references/pagination-and-export.md](references/pagination-and-export.md)** — Response modes, operationId polling, CSV export, field selection
    - **[references/twitter.md](references/twitter.md)** — All 13 Twitter tools with parameters, fields, and examples
    - **[references/instagram.md](references/instagram.md)** — All 9 Instagram tools with parameters, fields, and examples
    - **[references/reddit.md](references/reddit.md)** — All 9 Reddit tools with parameters, fields, and examples
    - **[references/tiktok.md](references/tiktok.md)** — All 9 TikTok tools with parameters, fields, and examples
    
    ## Example Prompts
    
    - "How do I search for tweets about AI?"
    - "What fields are available for Instagram posts?"
    - "How do I export Reddit data to CSV?"
    - "Set up tracking for my brand across all platforms"
    - "How do I paginate through large result sets?"
    - "What's the difference between fast mode and paging mode?"
    - "How do I authenticate with the Xpoz Python SDK?"
    - "Show me all available TikTok tools"
    

Comments (0)

Sign in to join the conversation.

No comments yet.

Reviews (0)

No reviews yet.

Related