Verify Airdrop & Giveaway Entries with Interaction Check API
The Problem: Manual Verification Doesn't Scale
Running an airdrop or giveaway on X/Twitter? You've probably seen the drill:
Manually checking 5,000 retweets and 5,000 replies is impossible. Many projects resort to random selection (unfair) or trusting participants (exploitable). Bots and fake entries slip through.
XCROP's Interaction Check API solves this. Six dedicated endpoints let you programmatically verify every single participant — retweets, replies, quotes, follow relationships, and account-quality filters — in minutes.
The 6 Interaction Check Endpoints
All endpoints return a simple boolean result — no complex parsing needed.
> Note on likes: X removed public like visibility in June 2024, so like-checking is not offered. Use retweet, reply, and quote checks instead — plus the qualified-account checks above to filter bot entries by account age, follower count, or display-name requirements.
Quick Start: Verify a Single User
import requests import os API_KEY = os.environ["XCROP_API_KEY"] HEADERS = {"Authorization": "Bearer " + API_KEY} BASE = "https://xcrop.io/api/v2" TWEET_ID = "1893045621038174208" # Check retweet rt = requests.get( BASE + "/tweets/" + TWEET_ID + "/check-retweet", headers=HEADERS, params={"username": "alice_crypto"} ).json() print("Retweeted:", rt["data"]["retweeted"]) # Check reply with 3 friend tags required reply = requests.get( BASE + "/tweets/" + TWEET_ID + "/check-reply", headers=HEADERS, params={"username": "alice_crypto", "min_tags": 3} ).json() print("Replied:", reply["data"]["replied"]) print("Tags met:", reply["data"]["tags_met"]) # Check follow relationship follow = requests.get( BASE + "/users/check-follow", headers=HEADERS, params={"source": "alice_crypto", "target": "your_project"} ).json() print("Follows you:", follow["data"]["source_follows_target"])
Bulk Verification: Check All Participants
Here's a complete script to verify an entire airdrop campaign:
import requests import time import os import json API_KEY = os.environ["XCROP_API_KEY"] HEADERS = {"Authorization": "Bearer " + API_KEY} BASE = "https://xcrop.io/api/v2" TWEET_ID = "1893045621038174208" PROJECT_USERNAME = "your_project" MIN_TAGS = 3 # List of participants (from your entry collection system) participants = ["alice_crypto", "bob_defi", "charlie_nft"] # ... thousands more def verify_participant(username): """Check all conditions for a single participant.""" result = {"username": username, "passed": False} # 1. Check retweet rt = requests.get( BASE + "/tweets/" + TWEET_ID + "/check-retweet", headers=HEADERS, params={"username": username} ).json() result["retweeted"] = rt["data"]["retweeted"] # 2. Check reply with friend tags reply = requests.get( BASE + "/tweets/" + TWEET_ID + "/check-reply", headers=HEADERS, params={"username": username, "min_tags": MIN_TAGS} ).json() result["replied"] = reply["data"]["replied"] result["tags_met"] = reply["data"].get("tags_met", False) # 3. Check follow follow = requests.get( BASE + "/users/check-follow", headers=HEADERS, params={"source": username, "target": PROJECT_USERNAME} ).json() result["follows"] = follow["data"]["source_follows_target"] # All conditions met? result["passed"] = ( result["retweeted"] and result["replied"] and result["tags_met"] and result["follows"] ) return result # Verify all participants verified = [] for i, user in enumerate(participants): try: result = verify_participant(user) verified.append(result) status = "PASS" if result["passed"] else "FAIL" print("[" + str(i + 1) + "/" + str(len(participants)) + "] @" + user + ": " + status) except Exception as e: print("[" + str(i + 1) + "] @" + user + ": ERROR - " + str(e)) time.sleep(0.1) # Be gentle with rate limits # Results winners = [r for r in verified if r["passed"]] print("\nTotal checked:", len(verified)) print("Qualified:", len(winners)) print("Disqualified:", len(verified) - len(winners)) # Save results with open("airdrop_results.json", "w") as f: json.dump({"winners": winners, "all": verified}, f, indent=2)
Tag Verification: Prevent Fake Entries
A common giveaway rule is "Reply and tag 3 friends." The check-reply and check-quote endpoints support the min_tags parameter to verify this automatically:
# Require at least 3 friend tags in the reply response = requests.get( BASE + "/tweets/" + TWEET_ID + "/check-reply", headers=HEADERS, params={"username": "alice_crypto", "min_tags": 3} ).json() data = response["data"] print("Replied:", data["replied"]) print("Tags required:", data["tags_required"]) # 3 print("Tags found:", data["tags_found"]) # 4 print("Tags met:", data["tags_met"]) # True
The tag count excludes the original tweet author — so if your tweet is from @project and Alice replies "@project @bob @carol @dave", the tag count is 3 (bob, carol, dave), not 4.
JavaScript / Node.js Example
const API_KEY = process.env.XCROP_API_KEY; const BASE = "https://xcrop.io/api/v2"; const TWEET_ID = "1893045621038174208"; async function checkInteractions(username) { const headers = { Authorization: "Bearer " + API_KEY }; const [retweet, reply, relationship] = await Promise.all([ fetch(BASE + "/tweets/" + TWEET_ID + "/check-retweet?username=" + username, { headers }).then(r => r.json()), fetch(BASE + "/tweets/" + TWEET_ID + "/check-reply?username=" + username + "&min_tags=3", { headers }).then(r => r.json()), fetch(BASE + "/users/check-follow?source=" + username + "&target=your_project", { headers }).then(r => r.json()), ]); return { username, retweeted: retweet.data.retweeted, replied: reply.data.replied, tags_met: reply.data.tags_met, follows: relationship.data.source_follows_target, qualified: retweet.data.retweeted && reply.data.replied && reply.data.tags_met && relationship.data.source_follows_target, }; } // Verify participants in parallel (batches of 10) async function verifyAll(participants) { const results = []; for (let i = 0; i < participants.length; i += 10) { const batch = participants.slice(i, i + 10); const batchResults = await Promise.all(batch.map(checkInteractions)); results.push(...batchResults); console.log("Checked " + results.length + "/" + participants.length); } return results; }
Cost Estimation
Each interaction check costs 50 credits. Here's what a typical campaign costs:
With the Pro plan ($9.9/month, includes 2M credits), you can verify ~13,000 users with all 3 checks included in your monthly allowance.
Pay-as-you-go credit packs start at $2.90 for 400K credits (~2,600 full verifications).
Best Practices
Promise.all (JS) or asyncio (Python) for 3 checks per user simultaneously