diff --git a/.github/skills/x-twitter-scraper/SKILL.md b/.github/skills/x-twitter-scraper/SKILL.md new file mode 100644 index 00000000..b47423d3 --- /dev/null +++ b/.github/skills/x-twitter-scraper/SKILL.md @@ -0,0 +1,284 @@ +--- +name: x-twitter-scraper +description: >- + X (Twitter) real-time data platform via Xquik REST API. + Use when building X/Twitter integrations, scraping tweets, extracting user data, + monitoring accounts, running giveaway draws, or composing tweets. + Triggers: "twitter api", "x api", "tweet search", "twitter scraper", "tweet data", + "follower extraction", "twitter monitoring", "giveaway draw". +--- + +# X (Twitter) Data Platform — Xquik REST API + +Real-time X (Twitter) data access via the Xquik REST API. 120 endpoints, 2 MCP tools, HMAC webhooks, 23 bulk extraction types. + +## Quick Start + +```bash +# Get an API key at https://xquik.com +# Set the header: X-API-Key: +BASE=https://api.xquik.com/v1 +``` + +## Authentication + +All requests require an `X-API-Key` header: + +```bash +curl -H "X-API-Key: $XQUIK_API_KEY" "$BASE/x/tweets/search?query=openai&type=latest" +``` + +## Environment Variables + +```bash +XQUIK_API_KEY=xq_... # API key from https://xquik.com/dashboard/account +``` + +--- + +## Core Operations + +### Tweet Search + +```bash +GET /x/tweets/search?query=from:elonmusk&type=latest +``` + +```typescript +const res = await fetch(`${BASE}/x/tweets/search?query=${encodeURIComponent(query)}&type=latest`, { + headers: { "X-API-Key": apiKey }, +}); +const { tweets, has_next_page, next_cursor } = await res.json(); +``` + +**Search operators**: `from:`, `to:`, `#hashtag`, `min_faves:`, `min_retweets:`, `filter:media`, `since:`, `until:`, `-filter:replies` + +### Tweet Lookup + +```bash +GET /x/tweets/:id +``` + +Returns full tweet object with `text`, `created_at`, `favorite_count`, `retweet_count`, `reply_count`, `quote_count`, `views`, `bookmark_count`, `media`, `author`. + +### User Lookup + +```bash +GET /x/users/:id +GET /x/users/by-username/:username +``` + +Returns `name`, `screen_name`, `followers_count`, `following_count`, `description`, `location`, `verified`, `created_at`, `profile_image_url`. + +### User Tweets + +```bash +GET /x/users/:id/tweets?cursor=... +``` + +### User Likes + +```bash +GET /x/users/:id/likes?cursor=... +``` + +--- + +## Write Actions + +```bash +POST /x/write/tweet # Post a tweet (body: { accountId, text }) +POST /x/write/like # Like (body: { accountId, tweetId }) +POST /x/write/retweet # Retweet (body: { accountId, tweetId }) +POST /x/write/follow # Follow (body: { accountId, targetUserId }) +POST /x/write/unfollow # Unfollow +POST /x/write/dm # Send DM (body: { accountId, recipientId, text }) +DELETE /x/write/tweet # Delete tweet +POST /x/write/unlike # Unlike +POST /x/write/upload-media # Upload media (multipart/form-data) +``` + +--- + +## Bulk Extraction + +23 extraction types for large datasets. Returns paginated results. + +```bash +POST /extractions +{ + "type": "replies", + "tweetId": "1234567890", + "maxResults": 1000 +} +``` + +**Extraction types**: `replies`, `retweets`, `quotes`, `favoriters`, `retweeters`, `followers`, `following`, `verified-followers`, `user-tweets`, `user-likes`, `user-media`, `mentions`, `search`, `thread`, `articles`, `community-members`, `community-posts`, `list-members`, `list-followers`, `space-participants`, `people-search`, `bookmarks`, `notifications` + +```bash +GET /extractions/:id # Check status +GET /extractions/:id/results # Get results (paginated) +GET /extractions/:id/export # Export as CSV/JSON +``` + +--- + +## Account Monitoring + +Track accounts for new tweets, replies, quotes, follower changes. + +```bash +POST /monitors +{ + "xAccountId": "44196397", + "events": ["new_tweet", "new_reply", "follower_change"] +} +``` + +### Webhooks + +Receive HMAC-SHA256 signed events at your endpoint: + +```bash +POST /webhooks +{ + "url": "https://example.com/webhook", + "events": ["monitor.new_tweet", "extraction.complete"] +} +``` + +**Signature verification** (Node.js): + +```typescript +import { createHmac } from "crypto"; + +function verify(body: string, signature: string, secret: string): boolean { + const expected = createHmac("sha256", secret).update(body).digest("hex"); + return signature === `sha256=${expected}`; +} +``` + +--- + +## Giveaway Draws + +Run transparent random draws from tweet replies: + +```bash +POST /draws +{ + "tweetId": "1234567890", + "winnerCount": 3, + "filters": { + "mustFollow": ["44196397"], + "mustLike": true, + "mustRetweet": true, + "minFollowers": 100, + "excludeBots": true + } +} +``` + +--- + +## Trending Topics + +```bash +GET /x/trends?country=US +``` + +### Radar (Free) + +Trending news from 7 sources (Google Trends, Hacker News, Polymarket, Wikipedia, GitHub, Reddit): + +```bash +GET /radar +``` + +--- + +## Tweet Composition (Free) + +Algorithm-optimized tweet composer with scoring: + +```bash +POST /compose +{ + "topic": "AI agents are changing software development", + "style": "professional", + "action": "compose" +} +``` + +--- + +## MCP Server + +2 tools via StreamableHTTP: + +| Tool | Purpose | +|------|---------| +| `explore` | Search the API spec (free, no network calls) | +| `xquik` | Execute any API call with auto-injected auth | + +**MCP config** (Claude Code): + +```json +{ + "mcpServers": { + "xquik": { + "type": "streamable-http", + "url": "https://xquik.com/mcp", + "headers": { "X-API-Key": "xq_..." } + } + } +} +``` + +--- + +## Pagination + +All list endpoints support cursor-based pagination: + +```typescript +let cursor: string | undefined; +const allResults = []; + +do { + const url = new URL(`${BASE}/x/tweets/search`); + url.searchParams.set("query", query); + if (cursor) url.searchParams.set("cursor", cursor); + + const res = await fetch(url, { headers: { "X-API-Key": apiKey } }); + const data = await res.json(); + allResults.push(...data.tweets); + cursor = data.has_next_page ? data.next_cursor : undefined; +} while (cursor); +``` + +--- + +## Error Handling + +| Status | Meaning | Action | +|--------|---------|--------| +| 400 | Invalid parameters | Check request body/query params | +| 401 | Invalid API key | Verify `X-API-Key` header | +| 402 | Insufficient credits | Top up via `POST /credits/topup` | +| 429 | Rate limited | Retry with exponential backoff | +| 500 | Server error | Retry (max 3 attempts) | + +--- + +## Pricing + +Reads from $0.00015/call. Writes $0.0003/call. Extractions $0.00015-$0.00105/result. Monitors, webhooks, radar, compose: free. + +Plans: Starter $20/mo, Pro $99/mo, Business $199/mo. Pay-per-use credits available ($10 minimum top-up). + +## Reference Files + +| File | Contents | +|------|----------| +| [references/endpoints.md](references/endpoints.md) | Complete endpoint reference (120 endpoints) | diff --git a/.github/skills/x-twitter-scraper/references/endpoints.md b/.github/skills/x-twitter-scraper/references/endpoints.md new file mode 100644 index 00000000..2a9c0c95 --- /dev/null +++ b/.github/skills/x-twitter-scraper/references/endpoints.md @@ -0,0 +1,231 @@ +# Xquik REST API — Complete Endpoint Reference + +Base URL: `https://api.xquik.com/v1` +Auth: `X-API-Key` header on all requests. + +--- + +## X Lookups + +| Method | Path | Description | Credits | +|--------|------|-------------|---------| +| GET | `/x/tweets/search` | Search tweets (query, type, cursor) | 1 | +| GET | `/x/tweets/:id` | Tweet lookup | 1 | +| GET | `/x/tweets/:id/replies` | Tweet replies | 1 | +| GET | `/x/tweets/:id/quotes` | Quote tweets | 1 | +| GET | `/x/tweets/:id/retweeters` | Retweeters | 1 | +| GET | `/x/tweets/:id/favoriters` | Who liked the tweet | 2 | +| GET | `/x/tweets/:id/thread` | Full thread | 1 | +| GET | `/x/tweets/:id/article` | Linked article content | 7 | +| GET | `/x/tweets/:id/download-media` | Download media (images, video, GIFs) | 1 | +| GET | `/x/users/:id` | User profile by ID | 2 | +| GET | `/x/users/by-username/:username` | User profile by username | 2 | +| GET | `/x/users/:id/tweets` | User's tweets | 1 | +| GET | `/x/users/:id/likes` | User's liked tweets | 1 | +| GET | `/x/users/:id/media` | User's media tweets | 1 | +| GET | `/x/users/:id/followers-you-know` | Mutual followers | 2 | +| GET | `/x/users/:id/verified-followers` | Verified followers | 2 | +| GET | `/x/follow-check` | Check mutual follow (query: sourceId, targetId) | 7 | +| GET | `/x/bookmarks` | User bookmarks | 1 | +| GET | `/x/bookmark-folders` | Bookmark folders | 1 | +| GET | `/x/notifications` | Notifications | 1 | +| GET | `/x/timeline` | Home timeline | 1 | +| GET | `/x/dm-history` | DM conversation history | 1 | +| GET | `/x/trends` | Trending topics by country | 3 | + +## Extractions + +| Method | Path | Description | +|--------|------|-------------| +| POST | `/extractions` | Create extraction (23 types) | +| GET | `/extractions` | List extractions | +| GET | `/extractions/estimate` | Estimate cost | +| GET | `/extractions/:id` | Get extraction status | +| GET | `/extractions/:id/results` | Get results (paginated) | +| GET | `/extractions/:id/export` | Export as CSV or JSON | + +### Extraction Types (23) + +| Type | Input | Credits/Result | +|------|-------|---------------| +| `replies` | tweetId | 1 | +| `retweets` | tweetId | 1 | +| `quotes` | tweetId | 1 | +| `favoriters` | tweetId | 2 | +| `retweeters` | tweetId | 2 | +| `followers` | userId | 2 | +| `following` | userId | 2 | +| `verified-followers` | userId | 2 | +| `user-tweets` | userId | 1 | +| `user-likes` | userId | 1 | +| `user-media` | userId | 1 | +| `mentions` | userId | 1 | +| `search` | query | 1 | +| `thread` | tweetId | 1 | +| `articles` | tweetId | 7 | +| `community-members` | communityId | 2 | +| `community-posts` | communityId | 1 | +| `list-members` | listId | 2 | +| `list-followers` | listId | 2 | +| `space-participants` | spaceId | 2 | +| `people-search` | query | 2 | +| `bookmarks` | accountId | 1 | +| `notifications` | accountId | 1 | + +## Monitors + +| Method | Path | Description | +|--------|------|-------------| +| POST | `/monitors` | Create monitor | +| GET | `/monitors` | List monitors | +| GET | `/monitors/:id` | Get monitor | +| PATCH | `/monitors/:id` | Update monitor | +| DELETE | `/monitors/:id` | Delete monitor | + +**Monitor events**: `new_tweet`, `new_reply`, `new_quote`, `new_retweet`, `follower_change` + +## Events + +| Method | Path | Description | +|--------|------|-------------| +| GET | `/events` | List events (filterable) | +| GET | `/events/:id` | Get single event | + +## Webhooks + +| Method | Path | Description | +|--------|------|-------------| +| POST | `/webhooks` | Create webhook | +| GET | `/webhooks` | List webhooks | +| PATCH | `/webhooks/:id` | Update webhook | +| DELETE | `/webhooks/:id` | Delete webhook | +| POST | `/webhooks/:id/test` | Send test event | +| GET | `/webhooks/:id/deliveries` | Delivery history | + +## Draws (Giveaways) + +| Method | Path | Description | +|--------|------|-------------| +| POST | `/draws` | Create draw | +| GET | `/draws` | List draws | +| GET | `/draws/:id` | Get draw with winners | +| GET | `/draws/:id/export` | Export results | + +### Draw Filters + +| Filter | Type | Description | +|--------|------|-------------| +| `mustFollow` | string[] | Must follow these user IDs | +| `mustLike` | boolean | Must have liked the tweet | +| `mustRetweet` | boolean | Must have retweeted | +| `mustReply` | boolean | Must have replied | +| `mustQuote` | boolean | Must have quote-tweeted | +| `minFollowers` | number | Minimum follower count | +| `maxFollowers` | number | Maximum follower count | +| `minAccountAge` | number | Minimum account age in days | +| `excludeBots` | boolean | Exclude likely bot accounts | +| `includeKeywords` | string[] | Reply must contain keywords | +| `excludeKeywords` | string[] | Reply must not contain keywords | + +## Write Actions + +| Method | Path | Description | Credits | +|--------|------|-------------|---------| +| POST | `/x/write/tweet` | Post tweet | 2 | +| DELETE | `/x/write/tweet` | Delete tweet | 2 | +| POST | `/x/write/like` | Like tweet | 2 | +| POST | `/x/write/unlike` | Unlike tweet | 2 | +| POST | `/x/write/retweet` | Retweet | 2 | +| POST | `/x/write/follow` | Follow user | 2 | +| POST | `/x/write/unfollow` | Unfollow user | 2 | +| POST | `/x/write/dm` | Send DM | 2 | +| POST | `/x/write/profile` | Update profile | 2 | +| POST | `/x/write/avatar` | Update avatar | 2 | +| POST | `/x/write/banner` | Update banner | 2 | +| POST | `/x/write/upload-media` | Upload media | 2 | +| POST | `/x/write/community/join` | Join community | 2 | +| POST | `/x/write/community/leave` | Leave community | 2 | + +## Trends & Radar + +| Method | Path | Description | Credits | +|--------|------|-------------|---------| +| GET | `/x/trends` | Regional trending topics | 3 | +| GET | `/radar` | Trending from 7 sources | 0 (free) | + +## Compose & Drafts + +| Method | Path | Description | Credits | +|--------|------|-------------|---------| +| POST | `/compose` | Compose/refine/score tweet | 0 (free) | +| POST | `/drafts` | Save draft | 0 (free) | +| GET | `/drafts` | List drafts | 0 (free) | +| GET | `/drafts/:id` | Get draft | 0 (free) | +| DELETE | `/drafts/:id` | Delete draft | 0 (free) | + +## Styles + +| Method | Path | Description | Credits | +|--------|------|-------------|---------| +| POST | `/styles/analyze` | Analyze tweet style | 0 (free) | +| POST | `/styles` | Save style | 0 (free) | +| GET | `/styles` | List styles | 0 (free) | +| GET | `/styles/:id` | Get style | 0 (free) | +| DELETE | `/styles/:id` | Delete style | 0 (free) | +| POST | `/styles/compare` | Compare styles | 0 (free) | +| POST | `/styles/performance` | Style performance | 0 (free) | + +## Account & Billing + +| Method | Path | Description | +|--------|------|-------------| +| GET | `/account` | Get account info | +| PATCH | `/account/locale` | Update locale | +| POST | `/account/x-identity` | Set X identity | +| POST | `/account/subscribe` | Subscribe to plan | +| GET | `/credits/balance` | Credit balance | +| POST | `/credits/topup` | Top up credits | +| POST | `/api-keys` | Create API key | +| GET | `/api-keys` | List API keys | +| DELETE | `/api-keys/:id` | Revoke API key | + +## X Accounts + +| Method | Path | Description | +|--------|------|-------------| +| POST | `/x-accounts/connect` | Connect X account | +| GET | `/x-accounts` | List connected accounts | +| GET | `/x-accounts/:id` | Get account details | +| DELETE | `/x-accounts/:id` | Disconnect account | +| POST | `/x-accounts/:id/re-auth` | Re-authenticate | + +## Integrations + +| Method | Path | Description | +|--------|------|-------------| +| POST | `/integrations` | Create (Telegram) | +| GET | `/integrations` | List integrations | +| GET | `/integrations/:id` | Get integration | +| PATCH | `/integrations/:id` | Update integration | +| DELETE | `/integrations/:id` | Delete integration | +| POST | `/integrations/:id/test` | Send test event | +| GET | `/integrations/:id/deliveries` | Delivery history | + +## Support + +| Method | Path | Description | +|--------|------|-------------| +| POST | `/support` | Create ticket | +| GET | `/support` | List tickets | +| GET | `/support/:id` | Get ticket | + +## Flows + +| Method | Path | Description | +|--------|------|-------------| +| POST | `/flows` | Create flow | +| GET | `/flows` | List flows | +| GET | `/flows/:id` | Get flow | +| PATCH | `/flows/:id` | Update flow | +| DELETE | `/flows/:id` | Delete flow | +| GET | `/flows/:id/runs` | Get flow runs |