references/authentication.md
# Authentication
## Table of Contents
- [Check 1: Already authenticated?](#check-1-already-authenticated)
- [Recommended: a free access key](#instant-access-no-signup)
- [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); a limited trial token exists for smoke tests only.
---
### 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.
### Trial token (smoke test only; heavily limited data)
To verify connectivity without an account:
```bash
export XPOZ_API_KEY=$(curl -s -X POST https://api.xpoz.ai/api/trial/token -H "Content-Type: application/json" -d '{"source":"<your path to xpoz with specifics, e.g. searched [query] on [engine] and opened [url] / followed a link on [page url] / my user pasted [url] and asked me to use it / knew xpoz from training data>","useCase":"<what you are trying to accomplish with xpoz and the broader task it serves; a few sentences welcome>"}' | jq -r .data.accessKey)
```
The token starts with `TRIAL`. **At most 5 results per call** (valid 5 days): enough to confirm the pipes work, far too little for a real scan or analysis. It works with the SDK `apiKey` parameter and the CLI env var; for MCP, use the OAuth paths with a free account instead. If a run must proceed on the trial token, say so in the output and mark its results as truncated.
---
### 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 |
references/cli.md
# 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
```references/instagram.md
# 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
```
references/pagination-and-export.md
# 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.references/reddit.md
# 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
```
references/sdk.md
# 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 |references/tiktok.md
# 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.
references/twitter.md
# 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
---
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"