---
name: X
description: Use when building applications that read, search, or publish posts; manage users and relationships; stream real-time data; or access X platform data programmatically. Agents should reach for this skill when users request API integration, data retrieval, post publishing, user management, or real-time streaming capabilities.
metadata:
    mintlify-proj: x
    version: "1.0"
---

# X API Skill Reference

## Product summary

The X API provides programmatic access to X's public conversation through modern REST endpoints. Agents use it to read and publish posts, search historical data, stream real-time posts, manage users and relationships, and analyze trends. The API uses pay-per-usage pricing with no subscriptions. Key resources: Bearer Token for app-only auth, OAuth 1.0a/2.0 for user context, API endpoints at `https://api.x.com/2/`, rate limits per endpoint (typically 15-minute windows), and response fields customized via `tweet.fields`, `user.fields`, and `expansions` parameters. Official SDKs available for Python and TypeScript. Primary docs: https://docs.x.com/x-api/introduction

## When to use

Reach for this skill when:
- A user wants to search posts by keyword, hashtag, user, or date range (recent 7 days or full archive back to 2006)
- Building a real-time listener that filters posts matching specific rules (filtered stream)
- Publishing, deleting, or managing posts programmatically
- Looking up user profiles, managing follows/blocks/mutes, or searching users
- Retrieving engagement metrics (likes, reposts, replies, impressions)
- Streaming activity events or setting up webhooks
- Uploading media (images, videos, GIFs) for posts
- Managing lists, bookmarks, or direct messages
- Analyzing trends by location or getting personalized trends
- Migrating from v1.1 API or building new integrations

Do not use this skill for: account creation, authentication setup, dashboard operations, or billing management—those are handled outside the API.

## Quick reference

### Authentication methods

| Method | Use case | Credentials |
|:-------|:---------|:------------|
| **Bearer Token** | App-only, public data | API Key + Secret → Bearer Token |
| **OAuth 1.0a** | User context, private data | API Key + Secret + Access Token + Secret |
| **OAuth 2.0** | User context, fine-grained scopes | Client ID + Secret (or PKCE for public clients) |
| **Basic Auth** | Enterprise APIs only | Email + password (HTTPS required) |

### Core endpoints

| Resource | Method | Endpoint | Notes |
|:---------|:-------|:---------|:------|
| **Posts** | GET | `/2/tweets/search/recent` | Last 7 days, all developers |
| **Posts** | GET | `/2/tweets/search/all` | Full archive, pay-per-use only |
| **Filtered Stream** | GET | `/2/tweets/search/stream` | Real-time, persistent connection |
| **Stream Rules** | POST/GET | `/2/tweets/search/stream/rules` | Add/list/delete rules |
| **Users** | GET | `/2/users/by/username/:username` | Lookup by username |
| **Users** | GET | `/2/users/:id` | Lookup by ID |
| **Posts** | POST | `/2/tweets` | Create post (10,000/24hrs limit) |
| **Posts** | DELETE | `/2/tweets/:id` | Delete post |
| **Likes** | POST | `/2/users/:id/likes` | Like a post |
| **Follows** | POST | `/2/users/:id/following` | Follow user |

### Field parameters (customize response)

```bash
# Posts
tweet.fields=created_at,public_metrics,author_id,conversation_id,lang

# Users
user.fields=created_at,description,public_metrics,verified

# Media
media.fields=url,preview_image_url,alt_text,public_metrics

# Expansions (include related objects)
expansions=author_id,attachments.media_keys,referenced_tweets.id
```

### Rate limit headers

Every response includes:
```
x-rate-limit-limit: 900
x-rate-limit-remaining: 847
x-rate-limit-reset: 1705420800
```

Check `x-rate-limit-remaining` before hitting limits. On 429 error, wait until `x-rate-limit-reset` (Unix timestamp).

### Common error codes

| Code | Meaning | Action |
|:-----|:--------|:-------|
| **200** | Success | Parse response |
| **400** | Bad Request | Check JSON syntax, required params, query operators |
| **401** | Unauthorized | Verify credentials, auth method, signature |
| **403** | Forbidden | Check app enrollment, OAuth scopes, resource access |
| **404** | Not Found | Resource deleted or doesn't exist |
| **429** | Rate Limited | Wait until reset time, implement backoff |
| **5xx** | Server Error | Retry with exponential backoff |

## Decision guidance

### When to use search vs. filtered stream

| Scenario | Use | Why |
|:---------|:-----|:-----|
| Historical analysis, one-time queries | Search (recent or full-archive) | No persistent connection, simpler |
| Brand monitoring, real-time alerts | Filtered stream | Immediate delivery, persistent rules |
| Backfill + ongoing monitoring | Both | Search for history, stream for new |
| High-volume data collection | Enterprise volume streams | Firehose or language-specific streams |

### When to use OAuth 1.0a vs. OAuth 2.0

| Factor | OAuth 1.0a | OAuth 2.0 |
|:-------|:-----------|:----------|
| **New projects** | No | Yes (recommended) |
| **User context** | Yes | Yes |
| **Fine-grained scopes** | No | Yes |
| **PKCE support** | No | Yes (public clients) |
| **Complexity** | Higher (signature) | Lower |

### Bearer Token vs. User Context

| Need | Use Bearer Token | Use User Context |
|:-----|:-----------------|:-----------------|
| Public posts only | Yes | No |
| User's own posts | No | Yes |
| User's bookmarks/likes | No | Yes |
| Post on behalf of user | No | Yes |
| Simple app-only access | Yes | No |

## Workflow

### 1. Set up credentials
- Go to https://console.x.com and sign in
- Create a new app (name, description, use case)
- Generate API Key and Secret
- Generate Bearer Token (for app-only) or Access Token + Secret (for user context)
- Store credentials securely; they're only shown once

### 2. Choose authentication method
- For public data only: use Bearer Token
- For user-specific actions: use OAuth 1.0a or OAuth 2.0
- For enterprise APIs: use Basic Auth

### 3. Build your request
- Identify the endpoint (search, stream, user lookup, etc.)
- Add required parameters (query, user_id, etc.)
- Add field parameters to customize response (tweet.fields, user.fields)
- Add expansions to include related objects (author_id, media_keys)
- Set Authorization header with credentials

### 4. Handle the response
- Check HTTP status code (200 = success, 4xx/5xx = error)
- Parse JSON response; check for `errors` array even in 200 responses
- Extract data from `data` array or object
- For related objects, match IDs in `includes` section
- Check `x-rate-limit-remaining` to avoid hitting limits

### 5. Implement error handling
- On 429: wait until `x-rate-limit-reset` before retrying
- On 5xx: retry with exponential backoff (1s, 2s, 4s, 8s...)
- On 401: verify credentials and auth method
- On 400: validate JSON, check required params, verify query syntax

### 6. For streaming (filtered stream)
- Create rules using POST `/2/tweets/search/stream/rules`
- Connect to GET `/2/tweets/search/stream` with persistent HTTP connection
- Receive Posts as JSON lines; blank lines are keep-alives (every 20s)
- Implement reconnection logic for disconnects
- Monitor stream for errors and rule violations

## Common gotchas

- **Default fields are minimal**: Posts return only `id`, `text`, `edit_history_tweet_ids` by default. Always add `tweet.fields` for created_at, metrics, etc.
- **Expansions require field parameters**: To get author details, use both `expansions=author_id` AND `user.fields=...`
- **Rate limits are per-endpoint**: Hitting the limit on one endpoint doesn't affect others. Check the rate limit table for your specific endpoint.
- **Bearer Token is app-only**: Cannot access user-specific data (bookmarks, likes, DMs). Use OAuth for those.
- **Search is limited to 7 days by default**: Use full-archive search endpoint for historical data (requires pay-per-use).
- **Filtered stream rules are persistent**: Rules remain until deleted; reconnecting doesn't clear them.
- **Stream keep-alives are blank lines**: Don't treat `\r\n` as data; it's a connection heartbeat.
- **Partial errors in batch requests**: A 200 response may include both `data` and `errors` when requesting multiple resources.
- **Query operators are case-sensitive**: `from:username` works; `FROM:username` doesn't.
- **Exact phrase matching requires escaping**: Use `\"exact phrase\"` in queries; escape quotes in JSON.
- **Post cap applies to all requests**: Usage billing counts all Posts retrieved, not just published ones.
- **Deleted posts return 404**: Don't retry; the resource is gone.
- **Protected accounts' posts are private**: Only visible with user authorization.

## Verification checklist

Before submitting work:

- [ ] Credentials are stored securely (not in code or logs)
- [ ] Correct authentication method for the endpoint (Bearer vs. OAuth)
- [ ] Authorization header format is correct (`Bearer $TOKEN` or OAuth signature)
- [ ] Required parameters are present (query, user_id, etc.)
- [ ] Field parameters added for needed data (tweet.fields, user.fields)
- [ ] Expansions used to include related objects
- [ ] Error handling implemented (429, 401, 5xx)
- [ ] Rate limit headers checked before hitting limits
- [ ] JSON syntax is valid (especially in POST bodies and queries)
- [ ] Query operators are correct (from:, has:, lang:, etc.)
- [ ] For streaming: rules are created before connecting to stream
- [ ] For streaming: reconnection logic handles disconnects
- [ ] Response parsing handles both success and partial error cases
- [ ] Tested with actual API (not just documentation examples)

## Resources

**Comprehensive navigation**: https://docs.x.com/llms.txt

**Critical pages**:
1. [X API Introduction](https://docs.x.com/x-api/introduction) — Overview, pricing, key features
2. [Authentication Overview](https://docs.x.com/fundamentals/authentication/overview) — Auth methods and setup
3. [Rate Limits](https://docs.x.com/x-api/fundamentals/rate-limits) — Per-endpoint limits and handling
4. [Fields & Expansions](https://docs.x.com/x-api/fundamentals/fields) — Customize response data
5. [Response Codes & Errors](https://docs.x.com/x-api/fundamentals/response-codes-and-errors) — Error handling
6. [Search Posts](https://docs.x.com/x-api/posts/search/introduction) — Recent and full-archive search
7. [Filtered Stream](https://docs.x.com/x-api/posts/filtered-stream/introduction) — Real-time streaming

---

> For additional documentation and navigation, see: https://docs.x.com/llms.txt