Try Live
Add Docs
Rankings
Pricing
Enterprise
Docs
Install
Theme
Install
Docs
Pricing
Enterprise
More...
More...
Try Live
Rankings
Create API Key
Add Docs
Xquik
https://github.com/xquik-dev/xquik-docs
Admin
Xquik is an X (Twitter) real-time data platform for extracting followers, running giveaway draws,
...
Tokens:
390,727
Snippets:
1,577
Trust Score:
7.5
Update:
2 days ago
Context
Skills
Chat
Benchmark
86.4
Suggestions
Latest
Show doc for...
Code
Info
Show Results
Context Summary (auto-generated)
Raw
Copy
Link
# Xquik API Documentation Xquik is an X (Twitter) real-time data platform providing programmatic access to X data, account monitoring, giveaway draws, data extractions, and write actions through a REST API, webhooks, and an MCP server. It targets developers and AI agents that need to pull followers, search tweets, monitor accounts in real time, run transparent giveaway draws, post content from connected X accounts, and surface multi-source trending topics — all through a single authenticated API at `https://xquik.com/api/v1`. The platform exposes five integration paths: a REST API (118 endpoints), HMAC-signed webhooks for real-time event delivery, an MCP server at `https://xquik.com/mcp` for AI agent tool use, an AI Coding Agent Skill (`npx skills add Xquik-dev/x-twitter-scraper`) for in-editor API knowledge, and a Machine Payments Protocol (MPP) layer for anonymous pay-per-call USDC access to 32 read-only endpoints. All endpoints are HTTPS-only, use `x-api-key` header authentication, return JSON error objects with machine-readable `error` codes, and share a 3-tier rate limit: 10 reads/s, 30 writes/60s, 15 deletes/60s. Credits power metered operations (1 credit ≈ $0.00012) with a $20/month subscription required for most endpoints. --- ## Authentication Every request requires the `x-api-key` header. Keys have the format `xq_` followed by 64 hex characters and are shown once at creation time. API key management endpoints require a session cookie instead of an API key. ```bash # Generate a key (session cookie required) curl -X POST https://xquik.com/api/v1/api-keys \ -H "Cookie: session_token=YOUR_SESSION" \ -H "Content-Type: application/json" \ -d '{"name": "Production"}' # Response: {"id":"42","name":"Production","fullKey":"xq_abc123...","createdAt":"2026-02-24T10:30:00.000Z"} # Use the key on any endpoint curl https://xquik.com/api/v1/account \ -H "x-api-key: xq_YOUR_KEY_HERE" | jq # Response: {"plan":"active","monitorsUsed":0,"creditInfo":{"balance":"50000",...}} # Revoke a key curl -X DELETE https://xquik.com/api/v1/api-keys/42 \ -H "Cookie: session_token=YOUR_SESSION" # Store keys in environment variables export XQUIK_API_KEY=xq_YOUR_KEY_HERE ``` --- ## GET /account — Get account info Returns subscription status, monitor quotas, and credit balance. Use this to verify your API key is working and to check your remaining credits before running expensive operations. ```bash curl -s https://xquik.com/api/v1/account \ -H "x-api-key: xq_YOUR_KEY_HERE" | jq ``` ```javascript const res = await fetch("https://xquik.com/api/v1/account", { headers: { "x-api-key": process.env.XQUIK_API_KEY }, }); const account = await res.json(); // { plan: "active", monitorsUsed: 2, creditInfo: { balance: "48000", autoTopupEnabled: false, ... } } if (account.creditInfo.balance < 1000) { console.warn("Low credits, top up soon"); } ``` ```python import requests, os r = requests.get( "https://xquik.com/api/v1/account", headers={"x-api-key": os.environ["XQUIK_API_KEY"]}, ) # r.json() → {"plan": "active", "creditInfo": {"balance": "48000", ...}} assert r.status_code == 200, r.json()["error"] print(r.json()["creditInfo"]["balance"]) ``` --- ## POST /monitors — Create account monitor Starts real-time monitoring of an X account, checking every 1 second. Costs 1 credit for the username lookup plus 21 credits per active monitor hour. Returns a monitor ID used to query events and attach webhooks. ```bash curl -s -X POST https://xquik.com/api/v1/monitors \ -H "x-api-key: xq_YOUR_KEY_HERE" \ -H "Content-Type: application/json" \ -d '{"username": "elonmusk", "eventTypes": ["tweet.new", "tweet.reply", "tweet.quote", "tweet.retweet"]}' | jq # Response: {"id":"7","username":"elonmusk","xUserId":"44196397","isActive":true,"createdAt":"2026-02-24T10:30:00.000Z","nextBillingAt":"2026-02-24T11:30:00.000Z"} ``` ```python import requests, os r = requests.post( "https://xquik.com/api/v1/monitors", headers={"x-api-key": os.environ["XQUIK_API_KEY"]}, json={ "username": "elonmusk", "eventTypes": ["tweet.new", "tweet.reply"], }, ) if r.status_code == 409: print("Monitor already exists — use existing one") elif r.status_code == 201: monitor_id = r.json()["id"] print(f"Monitor created: {monitor_id}") else: raise Exception(r.json()["error"]) ``` --- ## GET /events — List monitor events Returns stored events from all active monitors with cursor-based pagination. Listing is free; events are retained after delivery. Filter by `monitorId` or `eventType` to scope results. ```bash # First page, scoped to monitor 7, new tweets only curl "https://xquik.com/api/v1/events?limit=50&monitorId=7&eventType=tweet.new" \ -H "x-api-key: xq_YOUR_KEY_HERE" | jq # Next page curl "https://xquik.com/api/v1/events?limit=50&monitorId=7&after=MjAyNi0wMi0yNFQxNTowNTozMC4wMDBafDkwMDI=" \ -H "x-api-key: xq_YOUR_KEY_HERE" | jq ``` ```javascript // Drain all events for a monitor async function drainEvents(monitorId, apiKey) { const allEvents = []; let cursor; do { const params = new URLSearchParams({ limit: "100", monitorId }); if (cursor) params.set("after", cursor); const data = await fetch(`https://xquik.com/api/v1/events?${params}`, { headers: { "x-api-key": apiKey }, }).then((r) => r.json()); allEvents.push(...data.events); cursor = data.hasMore ? data.nextCursor : undefined; } while (cursor); return allEvents; } // Each event: { id, type, monitorId, username, occurredAt, data: { id, text, author, ... } } ``` --- ## POST /webhooks — Create webhook Registers an HTTPS endpoint to receive real-time monitor events. Returns a `secret` (shown once) used to verify HMAC-SHA256 signatures on every delivery. Free — no credits consumed. ```bash curl -s -X POST https://xquik.com/api/v1/webhooks \ -H "x-api-key: xq_YOUR_KEY_HERE" \ -H "Content-Type: application/json" \ -d '{"url": "https://your-server.com/webhook", "eventTypes": ["tweet.new", "tweet.reply"]}' | jq # Response: {"id":"15","url":"https://your-server.com/webhook","eventTypes":["tweet.new","tweet.reply"], # "secret":"a1b2c3d4e5f6...","createdAt":"2026-02-24T10:30:00.000Z"} # ⚠ Save the "secret" — it is returned only once ``` ```python import requests, os r = requests.post( "https://xquik.com/api/v1/webhooks", headers={"x-api-key": os.environ["XQUIK_API_KEY"]}, json={"url": "https://your-server.com/webhook", "eventTypes": ["tweet.new"]}, ) webhook = r.json() # Store webhook["secret"] in your secret manager immediately print(f"Webhook {webhook['id']} created. Secret: {webhook['secret']}") ``` --- ## Webhook signature verification Every delivery carries three headers: `X-Xquik-Timestamp` (Unix ms), `X-Xquik-Nonce` (16 random hex bytes), and `X-Xquik-Signature` (`sha256=<hex>`). The HMAC is computed over `<timestamp>.<nonce>.<rawBody>` using the webhook secret. Reject stale (>5 min) and replayed nonces. ```javascript import { createHmac, timingSafeEqual } from "node:crypto"; import express from "express"; const FIVE_MINUTES_MS = 5 * 60 * 1000; const seenNonces = new Map(); function verifyWebhook(req, secret) { const timestamp = req.headers["x-xquik-timestamp"]; const nonce = req.headers["x-xquik-nonce"]; const signature = req.headers["x-xquik-signature"]; const rawBody = req.body.toString(); // must be raw bytes if (!timestamp || !nonce || !signature) return false; const ts = Number(timestamp); if (!Number.isFinite(ts) || Math.abs(Date.now() - ts) > FIVE_MINUTES_MS) return false; const now = Date.now(); for (const [n, exp] of seenNonces) if (exp <= now) seenNonces.delete(n); if (seenNonces.has(nonce)) return false; seenNonces.set(nonce, now + FIVE_MINUTES_MS); const expected = "sha256=" + createHmac("sha256", secret).update(`${timestamp}.${nonce}.${rawBody}`).digest("hex"); return timingSafeEqual(Buffer.from(expected), Buffer.from(signature)); } const app = express(); app.post("/webhook", express.raw({ type: "application/json" }), (req, res) => { if (!verifyWebhook(req, process.env.WEBHOOK_SECRET)) return res.status(401).send("Invalid signature"); const event = JSON.parse(req.body.toString()); // event.type: "tweet.new" | "tweet.reply" | "tweet.quote" | "tweet.retweet" // event.data: raw tweet object console.log(`[${event.type}] @${event.data.author?.userName}: ${event.data.text}`); res.status(200).send("OK"); }); ``` ```python import hmac, hashlib, time from flask import Flask, request app = Flask(__name__) FIVE_MINUTES_MS = 5 * 60 * 1000 _seen_nonces: dict[str, int] = {} def verify_webhook(req, secret: str) -> bool: timestamp = req.headers.get("X-Xquik-Timestamp", "") nonce = req.headers.get("X-Xquik-Nonce", "") signature = req.headers.get("X-Xquik-Signature", "") raw_body = req.get_data() if not (timestamp and nonce and signature): return False now_ms = int(time.time() * 1000) if abs(now_ms - int(timestamp)) > FIVE_MINUTES_MS: return False expired = [n for n, exp in _seen_nonces.items() if exp <= now_ms] for n in expired: _seen_nonces.pop(n, None) if nonce in _seen_nonces: return False _seen_nonces[nonce] = now_ms + FIVE_MINUTES_MS signing_string = f"{timestamp}.{nonce}.".encode() + raw_body expected = "sha256=" + hmac.new(secret.encode(), signing_string, hashlib.sha256).hexdigest() return hmac.compare_digest(expected, signature) @app.route("/webhook", methods=["POST"]) def webhook(): if not verify_webhook(request, "YOUR_WEBHOOK_SECRET"): return "Invalid signature", 401 event = request.get_json() print(f"[{event['type']}] {event['data']['text'][:80]}") return "OK", 200 ``` --- ## POST /extractions — Create extraction job Launches an asynchronous data extraction using one of 23 tool types (followers, replies, retweets, likes, community members, tweet search, people search, etc.). Returns immediately with a job ID. Poll `GET /extractions/{id}` until `status` is `completed`. Costs 1 credit per result. ```bash # Extract all replies to a tweet curl -s -X POST https://xquik.com/api/v1/extractions \ -H "x-api-key: xq_YOUR_KEY_HERE" \ -H "Content-Type: application/json" \ -d '{"toolType": "reply_extractor", "targetTweetId": "1893704267862470862"}' | jq # Response: {"id":"a1b2c3d4-e5f6-7890-abcd-ef1234567890","toolType":"reply_extractor","status":"running"} # Extract followers of an account (limit to 500) curl -s -X POST https://xquik.com/api/v1/extractions \ -H "x-api-key: xq_YOUR_KEY_HERE" \ -H "Content-Type: application/json" \ -d '{"toolType": "follower_explorer", "targetUsername": "elonmusk", "resultsLimit": 500}' | jq # Search tweets by keyword with filters curl -s -X POST https://xquik.com/api/v1/extractions \ -H "x-api-key: xq_YOUR_KEY_HERE" \ -H "Content-Type: application/json" \ -d '{ "toolType": "tweet_search_extractor", "searchQuery": "TypeScript", "language": "en", "sinceDate": "2026-01-01", "minFaves": 100, "retweets": "exclude", "resultsLimit": 200 }' | jq ``` ```python import requests, time, os api_key = os.environ["XQUIK_API_KEY"] headers = {"x-api-key": api_key} # Start extraction r = requests.post( "https://xquik.com/api/v1/extractions", headers=headers, json={"toolType": "repost_extractor", "targetTweetId": "1893704267862470862"}, ) job_id = r.json()["id"] # Poll until done while True: status_r = requests.get(f"https://xquik.com/api/v1/extractions/{job_id}", headers=headers) job = status_r.json()["job"] if job["status"] == "completed": print(f"Done: {job['totalResults']} results") break elif job["status"] == "failed": raise Exception(f"Extraction failed: {job.get('errorMessage')}") time.sleep(2) # Paginate through all results cursor = None all_results = [] while True: params = {"limit": 1000} if cursor: params["after"] = cursor page = requests.get(f"https://xquik.com/api/v1/extractions/{job_id}", headers=headers, params=params).json() all_results.extend(page["results"]) if not page["hasMore"]: break cursor = page["nextCursor"] print(f"Fetched {len(all_results)} records") # Each result: {xUserId, xUsername, xDisplayName, xFollowersCount, xVerified, tweetId, tweetText, ...} ``` --- ## GET /extractions/{id}/export — Export extraction results Downloads extraction results as CSV, XLSX, JSON, Markdown, PDF, or plain text. Free, no credits consumed. Capped at 100,000 rows (10,000 for PDF). Includes enrichment columns: follower counts, bio, engagement metrics, tweet text, and more. ```bash # Download as CSV curl -s "https://xquik.com/api/v1/extractions/a1b2c3d4-e5f6-7890-abcd-ef1234567890/export?format=csv" \ -H "x-api-key: xq_YOUR_KEY_HERE" \ -o extraction-results.csv # Download as XLSX curl -s "https://xquik.com/api/v1/extractions/a1b2c3d4-e5f6-7890-abcd-ef1234567890/export?format=xlsx" \ -H "x-api-key: xq_YOUR_KEY_HERE" \ -o extraction-results.xlsx ``` ```python import requests, os extraction_id = "a1b2c3d4-e5f6-7890-abcd-ef1234567890" r = requests.get( f"https://xquik.com/api/v1/extractions/{extraction_id}/export", headers={"x-api-key": os.environ["XQUIK_API_KEY"]}, params={"format": "csv"}, ) # Columns: User ID, Username, Display Name, Followers, Verified, Profile Image, # Following, Posts, Description, Location, Media Count, Favorites, Cover Picture, # Tweet ID, Tweet Text, Tweet Created At, Likes, Reposts, Replies, Quotes, Views, ... with open("extraction-results.csv", "wb") as f: f.write(r.content) print(f"Saved {len(r.content)} bytes") ``` --- ## POST /draws — Create giveaway draw Executes a transparent, auditable random draw on a tweet's replies. Supports filters for retweet requirement, follow requirement, minimum followers, account age, language, required keywords, hashtags, and mentions. Returns winners and backup winners immediately. ```bash curl -s -X POST https://xquik.com/api/v1/draws \ -H "x-api-key: xq_YOUR_KEY_HERE" \ -H "Content-Type: application/json" \ -d '{ "tweetUrl": "https://x.com/xquikcom/status/1893456789012345678", "winnerCount": 3, "backupCount": 2, "mustRetweet": true, "filterMinFollowers": 50, "filterAccountAgeDays": 30, "requiredKeywords": ["giveaway"], "requiredHashtags": ["#web3"], "uniqueAuthorsOnly": true }' | jq ``` ```javascript const res = await fetch("https://xquik.com/api/v1/draws", { method: "POST", headers: { "x-api-key": process.env.XQUIK_API_KEY, "Content-Type": "application/json", }, body: JSON.stringify({ tweetUrl: "https://x.com/xquikcom/status/1893456789012345678", winnerCount: 3, backupCount: 2, mustRetweet: true, filterMinFollowers: 10, }), }); if (!res.ok) { const err = await res.json(); // Handle: "no_credits", "tweet_not_found", "no_subscription" throw new Error(`Draw failed: ${err.error}`); } const draw = await res.json(); // { id, tweetId, totalEntries: 847, validEntries: 312, // winners: [{position:1, authorUsername:"alice_web3", tweetId:"...", isBackup:false}, ...] } const winners = draw.winners.filter((w) => !w.isBackup); const backups = draw.winners.filter((w) => w.isBackup); console.log("Winners:", winners.map((w) => `@${w.authorUsername}`).join(", ")); ``` --- ## GET /x/users/{id} — Get X user profile Looks up an X user by username or numeric ID. Returns full profile: followers, following, bio, location, verification status, pinned tweets, and more. Costs 1 credit per call. ```bash curl https://xquik.com/api/v1/x/users/xquikcom \ -H "x-api-key: xq_YOUR_KEY_HERE" | jq # Response: {"id":"987654321","username":"xquikcom","name":"Xquik","followers":10000, # "verified":true,"description":"X real-time data platform","canDm":true,...} ``` ```python import requests, os r = requests.get( "https://xquik.com/api/v1/x/users/elonmusk", headers={"x-api-key": os.environ["XQUIK_API_KEY"]}, ) if r.status_code == 404: print("User not found or suspended") else: user = r.json() print(f"@{user['username']} — {user.get('followers', 0):,} followers") print(f"Verified: {user.get('verified', False)}, Can DM: {user.get('canDm', False)}") ``` --- ## GET /x/tweets/search — Search tweets Searches tweets by keyword, hashtag, or X search operators with optional date range and sort order. Returns paginated results with full tweet metadata including author, engagement counts, media, quoted tweets, and more. Costs 1 credit per tweet returned. ```bash # Search for recent tweets about TypeScript curl -G "https://xquik.com/api/v1/x/tweets/search" \ --data-urlencode "q=TypeScript lang:en -is:retweet" \ --data-urlencode "queryType=Latest" \ --data-urlencode "limit=20" \ -H "x-api-key: xq_YOUR_KEY_HERE" | jq # Search tweets from a specific user with date range curl -G "https://xquik.com/api/v1/x/tweets/search" \ --data-urlencode "q=from:vercel" \ --data-urlencode "sinceTime=2026-01-01" \ --data-urlencode "untilTime=2026-03-01" \ -H "x-api-key: xq_YOUR_KEY_HERE" | jq ``` ```javascript // Paginate through all matching tweets async function searchAllTweets(query, apiKey) { const allTweets = []; let cursor; do { const params = new URLSearchParams({ q: query, limit: "200", queryType: "Latest" }); if (cursor) params.set("cursor", cursor); const data = await fetch(`https://xquik.com/api/v1/x/tweets/search?${params}`, { headers: { "x-api-key": apiKey }, }).then((r) => r.json()); allTweets.push(...data.tweets); cursor = data.has_next_page ? data.next_cursor : undefined; } while (cursor); return allTweets; // Each tweet: { id, text, createdAt, likeCount, retweetCount, replyCount, // viewCount, url, lang, author: {id, username, followers, verified}, media: [...] } } ``` --- ## POST /x/tweets — Create tweet (X Write) Posts a new tweet from a connected X account. Supports replies, quote tweets, media attachments (via image URLs), community posts, and long-form note tweets up to 25,000 characters. Costs 10 credits per call. The connected account must be added via the dashboard. ```bash # Post a plain tweet curl -s -X POST https://xquik.com/api/v1/x/tweets \ -H "x-api-key: xq_YOUR_KEY_HERE" \ -H "Content-Type: application/json" \ -d '{"account": "myusername", "text": "Hello from Xquik!"}' | jq # Response: {"tweetId":"1895432178065391234","success":true} # Reply to a tweet curl -s -X POST https://xquik.com/api/v1/x/tweets \ -H "x-api-key: xq_YOUR_KEY_HERE" \ -H "Content-Type: application/json" \ -d '{"account": "myusername", "text": "Great post!", "reply_to_tweet_id": "1893456789012345678"}' | jq # Tweet with media (pass public image URLs directly) curl -s -X POST https://xquik.com/api/v1/x/tweets \ -H "x-api-key: xq_YOUR_KEY_HERE" \ -H "Content-Type: application/json" \ -d '{"account": "myusername", "text": "Check this out!", "media": ["https://example.com/image.jpg"]}' | jq ``` ```python import requests, os r = requests.post( "https://xquik.com/api/v1/x/tweets", headers={"x-api-key": os.environ["XQUIK_API_KEY"]}, json={"account": "myusername", "text": "Hello from Xquik!"}, ) if r.status_code == 403 and r.json().get("error") == "account_needs_reauth": print("Reconnect your X account from the dashboard") elif r.status_code == 422: print(f"X rejected the tweet: {r.json()['error']}") elif r.ok: print(f"Posted tweet: {r.json()['tweetId']}") ``` --- ## GET /trends — List trending topics on X Returns trending topics for a specific region using WOEID codes. Covers 12 regions including Worldwide, US, UK, Turkey, Japan, India, Brazil, and more. Costs 3 credits per call. ```bash # Worldwide trends (top 30) curl "https://xquik.com/api/v1/trends?woeid=1&count=30" \ -H "x-api-key: xq_YOUR_KEY_HERE" | jq # US trends (top 50) curl "https://xquik.com/api/v1/trends?woeid=23424977&count=50" \ -H "x-api-key: xq_YOUR_KEY_HERE" | jq ``` ```python import requests, os # WOEID reference: 1=Worldwide, 23424977=US, 23424975=UK, 23424969=Turkey r = requests.get( "https://xquik.com/api/v1/trends", headers={"x-api-key": os.environ["XQUIK_API_KEY"]}, params={"woeid": 23424977, "count": 20}, ) data = r.json() # data = {"trends": [{"name": "#SuperBowl", "rank": 1, "query": "%23SuperBowl"}, ...], "total": 50, "woeid": 23424977} for trend in data["trends"]: print(f"#{trend['rank']} {trend['name']}") ``` --- ## GET /radar — Multi-source trending topics Aggregates trending topics and news from 7 sources: Google Trends, Hacker News, Polymarket, TrustMRR, Wikipedia, GitHub Trending, and Reddit. Free — no credits consumed. Supports filtering by source, category, region, and time window with cursor pagination. ```bash # Hacker News top stories from last 12 hours curl "https://xquik.com/api/v1/radar?source=hacker_news&hours=12&limit=10" \ -H "x-api-key: xq_YOUR_KEY_HERE" | jq # GitHub trending repos (dev category, US region) curl "https://xquik.com/api/v1/radar?source=github&category=dev®ion=US&hours=24" \ -H "x-api-key: xq_YOUR_KEY_HERE" | jq ``` ```javascript // Poll all Radar sources and compose a tweet about the top item const data = await fetch( "https://xquik.com/api/v1/radar?hours=6&limit=5&category=tech", { headers: { "x-api-key": process.env.XQUIK_API_KEY } }, ).then((r) => r.json()); for (const item of data.items) { // item: { id, title, description, url, source, category, region, score, // metadata: { points, numberComments } | { starsToday, language } | { subreddit } | ..., // publishedAt, createdAt } console.log(`[${item.source}] ${item.title} (score: ${item.score})`); } // Paginate: pass data.nextCursor as ?after= when data.hasMore === true ``` --- ## POST /compose — AI tweet composer Composes, refines, and scores tweet drafts against X algorithm ranking factors using a 3-step workflow: `compose` (get algorithm weights and questions), `refine` (get composition guidance), `score` (evaluate a draft with pass/fail checklist). Free — no credits consumed. ```bash # Step 1: compose — get algorithm context curl -s -X POST https://xquik.com/api/v1/compose \ -H "x-api-key: xq_YOUR_KEY_HERE" \ -H "Content-Type: application/json" \ -d '{"step": "compose", "topic": "launching my new SaaS", "goal": "engagement"}' | jq # Step 3: score — evaluate your draft curl -s -X POST https://xquik.com/api/v1/compose \ -H "x-api-key: xq_YOUR_KEY_HERE" \ -H "Content-Type: application/json" \ -d '{"step": "score", "draft": "Just shipped v2.0 of our API. What do you think?", "hasLink": false, "hasMedia": false}' | jq ``` ```javascript // Full 3-step compose workflow const apiKey = process.env.XQUIK_API_KEY; const post = (body) => fetch("https://xquik.com/api/v1/compose", { method: "POST", headers: { "x-api-key": apiKey, "Content-Type": "application/json" }, body: JSON.stringify(body), }).then((r) => r.json()); // Step 1: Get algorithm context const compose = await post({ step: "compose", topic: "my SaaS launch", goal: "engagement" }); // compose.followUpQuestions → ["What tone?", "Will you attach media?", ...] // Step 2: Refine with answers const refine = await post({ step: "refine", topic: "my SaaS launch", goal: "engagement", tone: "bold", mediaType: "photo" }); // refine.compositionGuidance, refine.examplePatterns // Step 3: Score your draft const score = await post({ step: "score", draft: "Shipped v2.0. Faster. Smarter. Ship yours.", hasMedia: true, hasLink: false }); // score.passed, score.passedCount, score.totalChecks, score.topSuggestion // score.checklist: [{factor: "No hashtags", passed: true}, {factor: "Sufficient substance", passed: false, suggestion: "..."}] console.log(`Score: ${score.passedCount}/${score.totalChecks} checks passed`); if (!score.passed) console.log("Top suggestion:", score.topSuggestion); ``` --- ## MCP Server — AI agent integration Xquik exposes a Model Context Protocol (MCP) server at `https://xquik.com/mcp` with two tools: `explore` (searches the API spec, free) and `xquik` (executes API calls). Supports API key auth (`x-api-key` header) or OAuth 2.1 (Bearer token for Claude.ai and ChatGPT Developer Mode). ```json // Claude Code: add to .mcp.json { "mcpServers": { "xquik": { "type": "http", "url": "https://xquik.com/mcp", "headers": { "x-api-key": "xq_YOUR_KEY_HERE" } } } } ``` ```json // Cursor: add to ~/.cursor/mcp.json or .cursor/mcp.json { "mcpServers": { "xquik": { "url": "https://xquik.com/mcp", "headers": { "x-api-key": "xq_YOUR_KEY_HERE" } } } } ``` ```python # OpenAI Agents SDK from agents.mcp import MCPServerStreamableHttp async with MCPServerStreamableHttp( url="https://xquik.com/mcp", headers={"x-api-key": "xq_YOUR_KEY_HERE"}, params={}, ) as xquik: # xquik tool: explore (spec search) + xquik (API execution) # Agents write JS arrow functions: async () => xquik.request('/api/v1/radar') pass ``` ```bash # AI Coding Agent Skill (Claude Code, Cursor, Copilot, Codex, Windsurf, and 35+ more) npx skills add Xquik-dev/x-twitter-scraper # Gives agents deep knowledge of all 118 REST ops + MCP tools without needing a live connection ``` --- ## Machine Payments Protocol (MPP) — Anonymous pay-per-call Thirty-two read-only X-API endpoints accept anonymous USDC micropayments via Tempo without requiring an account or API key. The server returns HTTP 402 with a `WWW-Authenticate: Payment` challenge; the client pays and retries with an `Authorization: Payment` credential. ```bash # 1. Call without credentials → 402 challenge curl -v https://xquik.com/api/v1/x/users/elonmusk 2>&1 | grep "WWW-Authenticate" # WWW-Authenticate: Payment id="...", realm="xquik.com", method="tempo", intent="charge", request="..." # 2. After Tempo payment, retry with credential curl https://xquik.com/api/v1/x/users/elonmusk \ -H 'Authorization: Payment <base64url-encoded-credential>' # 200 OK with Payment-Receipt header on success ``` ```python # MPP-eligible endpoints and per-call prices: # GET /x/users/{id} → $0.00015 (charge) # GET /x/tweets/search → $0.00015/tweet (session) # GET /x/tweets/{id} → $0.00015 (charge) # GET /x/followers/check → $0.00105 (charge) # GET /trends → $0.00045 (charge) # GET /x/users/{id}/tweets → $0.00015/tweet (session) # GET /x/tweets/{id}/replies → $0.00015/tweet (session) # ... 32 endpoints total — see /mpp/overview for full list # No account needed; payment IS the authentication. # MPP discovery: https://xquik.com/.well-known/mpp.json ``` --- ## Error handling and retries All errors return `{"error": "error_code", "message": "..."}`. Only `429` (rate limit) and `5xx` (server/upstream) errors are retryable. Use exponential backoff with jitter; respect the `Retry-After` header. The opt-in contract header `xquik-api-contract: 2026-04-29` upgrades error shapes, pagination fields, and `502` → `424` for upstream failures. ```javascript async function fetchWithRetry(url, options = {}, maxRetries = 3) { const baseDelay = 1000; for (let attempt = 0; attempt <= maxRetries; attempt++) { const response = await fetch(url, { ...options, headers: { "x-api-key": process.env.XQUIK_API_KEY, ...options.headers }, }); if (response.ok) return response.json(); const body = await response.json(); const retryable = response.status === 429 || response.status >= 500; if (!retryable || attempt === maxRetries) { // Non-retryable codes: invalid_input(400), unauthenticated(401), // no_subscription(402), insufficient_credits(402), not_found(404), // monitor_already_exists(409), x_content_too_long(422) throw new Error(`${response.status} ${body.error}: ${body.message ?? ""}`); } const retryAfter = response.headers.get("Retry-After"); const delay = retryAfter ? parseInt(retryAfter, 10) * 1000 : baseDelay * Math.pow(2, attempt) + Math.random() * 1000; await new Promise((res) => setTimeout(res, delay)); } } // Usage with opt-in response contract const events = await fetchWithRetry("https://xquik.com/api/v1/events?limit=50", { headers: { "xquik-api-contract": "2026-04-29" }, }); // opt-in: snake_case fields, has_more/next_cursor pagination, 424 for upstream failures ``` ```python import requests, time, random, os def fetch_with_retry(url, max_retries=3, **kwargs): base_delay = 1.0 headers = {"x-api-key": os.environ["XQUIK_API_KEY"], **kwargs.pop("headers", {})} for attempt in range(max_retries + 1): r = requests.get(url, headers=headers, **kwargs) if r.ok: return r.json() retryable = r.status_code == 429 or r.status_code >= 500 if not retryable or attempt == max_retries: raise Exception(f"{r.status_code} {r.json().get('error')}: {r.json().get('message','')}") retry_after = r.headers.get("Retry-After") delay = int(retry_after) if retry_after else base_delay * (2 ** attempt) + random.random() time.sleep(delay) ``` --- ## Summary Xquik's primary use cases fall into three categories. **Real-time monitoring and automation**: create account monitors, receive tweet events via HMAC-signed webhooks within seconds of posting, query stored events with cursor pagination, and chain monitors with webhooks to build notification pipelines, social listening dashboards, and automated response systems. **Data extraction and analysis**: run asynchronous extraction jobs using any of 23 tool types to pull followers, replies, retweets, community members, tweet search results, or space participants at scale, then export to CSV/XLSX/JSON for analysis or giveaway verification. **AI agent integration**: connect AI coding assistants (Claude Code, Cursor, Copilot, Windsurf) to the MCP server for natural-language X data operations, or install the Xquik Skill for offline API knowledge — enabling agents to write, test, and deploy Xquik integrations autonomously. Integration patterns follow a consistent structure across all SDKs and languages: authenticate with `x-api-key`, handle the `{"error": "error_code"}` shape for non-2xx responses, paginate with `nextCursor`/`after` for platform endpoints and `next_cursor`/`cursor` for X-API endpoints, and retry `429`/`5xx` with exponential backoff respecting the `Retry-After` header. For anonymous or low-volume scenarios, MPP enables pay-per-call access to 32 read-only endpoints without any account. For framework integrations, the MCP server supports LangChain, CrewAI, Pydantic AI, Google ADK, Mastra, and Microsoft Agent Framework through the standard StreamableHTTP transport at `https://xquik.com/mcp`.